这里是我所遇到的非常简化的问题代码:
enum node_type {
t_int, t_double
};
struct int_node {
int value;
};
struct double_node {
double value;
};
struct node {
enum node_type type;
union {
struct int_node int_n;
struct double_node double_n;
};
};
int main(void) {
struct int_node i;
i.value = 10;
struct node n;
n.type = t_int;
n.int_n = i;
return 0;
}
我不明白的是:
$ cc us.c
$ cc -std=c99 us.c
us.c:18:4: warning: declaration does not declare anything
us.c: In function ‘main’:
us.c:26:4: error: ‘struct node’ has no member named ‘int_n’
使用 GCC
没有 -std
选项编译上面的代码没有任何问题(类似的代码工作得很好),但似乎 c99
不允许这种技术 . 为什么会这样,是否可以使 c99
(或 c89
, c90
)兼容?谢谢 .
6 回答
匿名联合是GNU扩展,不是任何标准版本的C语言的一部分 . 对于c99 GNU扩展,你可以使用-std = gnu99或类似的东西,但是最好编写适当的C而不依赖于只提供语法糖的扩展......
Edit: 匿名工会在C11中被添加,因此它们现在是该语言的标准部分 . 据推测,GCC的
-std=c11
允许你使用它们 .我发现这个问题大约在其他人做了一年半之后,所以我可以给出一个不同的答案:匿名结构不符合C99标准,但它们符合C11标准 . GCC和clang已经支持这一点(C11标准似乎已经取消了微软的功能,GCC已经为一些MSFT扩展提供了一段时间的支持) .
好吧,解决方案是命名union的实例(可以作为数据类型保持匿名),然后使用该名称作为代理 .
现在它编译为
c99
没有任何问题 .注意:无论如何,我对这个解决方案并不满意 .
联盟必须有一个名称,并声明如下:
另一种解决方案是将公共标头值(
enum node_type type
)放入每个结构中,并使您的顶级结构成为一个联合 . 它不完全是"Don't Repeat Yourself",但它确实避免了匿名联合和不舒服的代理值 .查看C99的6.2.7.1,我发现标识符是可选的:
我一直在寻找,并且找不到任何匿名工会违反规范的提法 . 整个-opt后缀表示根据6.1,在这种情况下
identifier
是可选的 .