PAYATHON 2026

C99 标准是否允许匿名枚举?C11 是否也支持?

数据阿明

C99 和 C11 都允许题目中的匿名枚举。这里的“匿名”指省略了枚举标签名,这符合标准语法,不需要 GCC 扩展。题目中的嵌套结构体和联合体示例也符合 C99:它们的成员都有名称,没有使用 C11 引入的匿名成员特性。

C99 为什么允许匿名枚举?

C99 的整合勘误草案 N1256 在 §6.7.2.2 中给出的枚举定义语法允许省略 enum 与 { 之间的标识符,也就是枚举标签名。下面的声明因此是合法的,无须添加标签名或变量名,见 N1256 §6.7.2.2。

enum {
    VAL_A = 1,
    VAL_B = 2,
    VAL_C = 3
};

这段代码定义了一个没有标签名的枚举类型,并声明了 VAL_A、VAL_B 和 VAL_C 这些枚举常量。可以直接使用这些常量:

int value = VAL_B;

C11 草案 N1570 在 §6.7.2.2 中保留了相同的可选标签语法,所以这种写法在 C11 中也合法,见 N1570 §6.7.2.2。

原来的结构体示例为什么也符合 C99?

需要分别看类型是否有标签名,以及成员是否有名称。

题目中的两个内部结构体都没有标签名,它们对应的成员分别叫 case_a 和 case_b;内部联合体也没有标签名,对应的成员叫 u。C99 允许用没有标签名的结构体或联合体类型声明有名称的成员,相关语法见 N1256 §6.7.2.1。

因此,可以按成员层级访问它们:

struct named item = {0};
item.u.case_a.a = 1;

GCC 在 C99 模式下接受题目中的代码,符合标准规定,不能因此认定它启用了匿名成员扩展。

C11 的匿名结构体和匿名联合体有什么不同?

C11 所说的匿名结构体或匿名联合体,是没有名称的结构体或联合体成员,其类型定义也没有标签名。可以通过包含它们的对象直接访问内部成员,见 N1570 §6.7.2.1 第 13 段。

例如:

struct container {
    union {
        int number;
        char *text;
    };
};

void example(void)
{
    struct container item;
    item.number = 1;
}

这里的 union { ... }; 后面没有 u 这样的成员名称,所以可以写 item.number。这种匿名联合体成员是 C11 支持的特性。严格遵循 C99 的代码应给它添加成员名称,再通过该名称访问内部成员。

实际使用时如何选择?

如果只需要一组整数常量,可以保留题目中的匿名枚举。如果需要在其他位置通过类型名声明变量,可以为枚举添加标签名:

enum value_kind {
    VAL_A = 1,
    VAL_B = 2,
    VAL_C = 3
};

enum value_kind value = VAL_B;

判断代码是否符合 C99 时,应检查具体声明形式。省略类型标签名本身不意味着使用了扩展;题目中的枚举和有名称的嵌套成员都可以保留。

备注:内容仅供参考。