结构中的匿名联合不在c99中?

这里是非常简化的问题我有:

 enum node_type {
     t_int,t_double
 };

 struct int_node {
     int值;
 };

 struct double_node {
    双重价值;
 };

 struct node {
    枚举node_typetypes;
     联合{ 
          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;
     ñ。  int_n = i;
    返回0;
 }

我不明白的是:

 $ cc us.c 
 $ cc -std = c99 us.c 
 us.c:18:4:警告:声明不声明任何东西
 us.c:在函数'main'中:
 us.c:26:4:错误:“struct node”没有名为“int_n”的成员

使用没有-std选项的GCC没有任何问题编译上面的代码(和类似的代码工作得很好),但似乎c99不允许这种技术。 为什么是这样,是否有可能使c99 (或c89c90 )兼容? 谢谢。

匿名联合是GNU扩展,不是任何标准版本的C语言的一部分。 你可以使用-std = gnu99或类似于c99 + GNU扩展的东西,但最好编写适当的C,而不要依赖只提供语法糖的扩展。

编辑:匿名联合在C11中添加,所以他们现在是语言的标准部分。 据推测GCC的-std=c11可以让你使用它们。

我在其他人做了大约一年半的时间后发现了这个问题,所以我可以给出一个不同的答案:匿名结构不在C99标准中,但是它们是C11标准。 GCC和clang已经支持这个(C11标准似乎已经提升了微软的function,GCC已经为一些MSFT扩展提供了一段时间的支持)。

那么,解决scheme是命名联合实例(它可以保持匿名作为数据types),然后使用该名称作为代理。

 $ diff -u old_us.c us.c 
 --- old_us.c 2010-07-12 13:49:25.000000000 +0200
 +++ us.c 2010-07-12 13:49:02.000000000 +0200
 @@ -15,7 +15,7 @@
   联合{
      struct int_node int_n;
      struct double_node double_n;
 - };
 +}数据;
  };

  int main(void){
 @@ -23,6 +23,6 @@
    i.value = 10;
    struct node n;
    n.type = t_int;
 -  n.int_n = i;
 + n.data.int_n = i;
   返回0;
  }

现在它编译为c99没有任何问题。

 $ cc -std = c99 us.c 
 $ 

注意:我不喜欢这个解决scheme。

联盟必须有一个名称,并声明如下:

 union UPair { struct int_node int_n; struct double_node double_n; }; UPair X; X.int_n.value = 12; 

另一个解决scheme是将公共标题值( enum node_type type )放到每个结构中,并使顶层结构成为一个联合体。 这不完全是“不要重复自己”,但它确实避免匿名工会和不舒服的代理值。

 enum node_type { t_int, t_double }; struct int_node { enum node_type type; int value; }; struct double_node { enum node_type type; double value; }; union node { enum node_type type; struct int_node int_n; struct double_node double_n; }; int main(void) { union node n; n.type = t_int; // or n.int_n.type = t_int; n.int_n.value = 10; return 0; } 

看看C99的6.2.7.1,我看到标识符是可选的:

  struct-or-union-specifier: struct-or-union identifier-opt { struct-declaration-list } struct-or-union identifier struct-or-union: struct union struct-declaration-list: struct-declaration struct-declaration-list struct-declaration struct-declaration: specifier-qualifier-list struct-declarator-list ; specifier-qualifier-list: type-specifier specifier-qualifier-list-opt type-qualifier specifier-qualifier-list-opt 

我一直在上下search,找不到任何违背规范的匿名工会。 整个-opt后缀表示事件,在这种情况下identifier是根据6.1的可选项。