C语言 结构中的匿名联合不在 c99 中?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3228104/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Anonymous union within struct not in c99?
提问by Martin
here is very simplified code of problem I have:
这是我遇到的非常简化的问题代码:
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;
}
And what I don't undestand is this:
我不明白的是:
$ 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'
Using GCCwithout -stdoption compiles code above without any problems (and the similar code is working pretty well), but it seems that c99does not permit this technique. Why is it so and is it possible to make is c99(or c89, c90) compatible? Thanks.
使用GCCwithout -stdoption 编译上面的代码没有任何问题(并且类似的代码工作得很好),但似乎c99不允许这种技术。为什么会这样,是否可以使 is c99(或c89, c90) 兼容?谢谢。
回答by R.. GitHub STOP HELPING ICE
Anonymous unions are a GNU extension, not part of any standard version of the C language. You can use -std=gnu99 or something like that for c99+GNU extensions, but it's best to write proper C and not rely on extensions which provide nothing but syntactic sugar...
匿名联合是 GNU 扩展,不是任何标准版本的 C 语言的一部分。对于 c99+GNU 扩展,您可以使用 -std=gnu99 或类似的东西,但最好编写适当的 C,而不是依赖于只提供语法糖的扩展......
Edit:Anonymous unions were added in C11, so they are now a standard part of the language. Presumably GCC's -std=c11lets you use them.
编辑:匿名联合是在 C11 中添加的,因此它们现在是该语言的标准部分。大概 GCC-std=c11允许您使用它们。
回答by bk.
I'm finding this question about a year and a half after everybody else did, so I can give a different answer: anonymous structs are not in the C99 standard, but they are in the C11 standard. GCC and clang already support this (the C11 standard seems to have lifted the feature from Microsoft, and GCC has provided support for some MSFT extensions for some time).
我发现这个问题比其他人晚了大约一年半,所以我可以给出一个不同的答案:匿名结构不在 C99 标准中,但它们在 C11 标准中。GCC 和 clang 已经支持这一点(C11 标准似乎已经从微软取消了该功能,并且 GCC 已经提供了对一些 MSFT 扩展的支持一段时间)。
回答by Martin
Well, the solution was to name instance of the union (which can remain anonymous as datatype) and then use that name as a proxy.
嗯,解决方案是命名联合的实例(它可以作为数据类型保持匿名),然后使用该名称作为代理。
$ 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 @@
union {
struct int_node int_n;
struct double_node double_n;
- };
+ } data;
};
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;
return 0;
}
Now it compiles as c99without any problems.
现在它编译c99没有任何问题。
$ cc -std=c99 us.c $
Note: I am not happy about this solution anyway.
注意:无论如何,我对这个解决方案并不满意。
回答by Undefined Behavior
Just for clarifications about anonymous structor anonymous union.
只是为了澄清匿名struct或匿名union。
6.7.2.1 Structure and union specifiers
6.7.2.1 结构和联合说明符
An unnamed memberwhose type specifier is a structure specifier with no tagis called an anonymous structure; an unnamed memberwhose type specifier is a union specifier with no tagis called an anonymous union. The members of an anonymous structure or union are considered to be members of the containing structure or union. This applies recursively if the containing structure or union is also anonymous.
类型说明符是没有标记的结构说明符 的未命名成员称为匿名结构;类型说明符是没有标记的联合说明符的未命名成员称为匿名联合。匿名结构或联合的成员被认为是包含结构或联合的成员。如果包含结构或联合也是匿名的,这将递归地适用。
C99There are no anonymous struct or union
C99没有匿名结构体或联合体
Simplified: Type-specifierIdentifier{Declaration-list}Tags;
简化:类型说明符标识符{声明列表}标签;
- Type-specifier:
structorunion; - Identifier: optional, your custom name for the
structorunion; - Declaration-list: members, your variables, anonymous
structand anonymousunion - Tags: optional. If you have a
typedefin front of the Type-specifier, the Tagsare alias and not Tags.
- 类型说明符:
struct或union; - 标识符: 可选,您的自定义名称
structorunion; - 声明列表:成员,您的变量,匿名
struct和匿名union - 标签:可选。如果
typedef在Type-specifier前面有 a ,则标签是别名而不是标签。
It is a anonymous structor anonymous uniononly if it have no identifier and no tag, and exist inside another structor union.
只有当它没有标识符和标签,并且存在于另一个or 中时,它才是匿名的struct或匿名的。unionstructunion
struct s {
struct { int x; }; // Anonymous struct, no identifier and no tag
struct a { int x; }; // NOT Anonymous struct, has an identifier 'a'
struct { int x; } b; // NOT Anonymous struct, has a tag 'b'
struct c { int x; } C; // NOT Anonymous struct
};
struct s {
union { int x; }; // Anonymous union, no identifier and no tag
union a { int x; }; // NOT Anonymous union, has an identifier 'a'
union { int x; } b; // NOT Anonymous union, has a tag 'b'
union c { int x; } C; // NOT Anonymous union
};
typedefhell: if you have a typedefthe tag part is not a tag anymore, it is alias for that type.
typedef地狱:如果你有一个typedef标签部分不再是一个标签,它是该类型的别名。
struct a { int x; } A; // 'A' is a tag
union a { int x; } A; // 'A' is a tag
// But if you use this way
typedef struct b { int x; } B; // 'B' is NOT a tag. It is an alias to struct 'b'
typedef union b { int x; } B; // 'B' is NOT a tag. It is an alias to union 'b'
// Usage
A.x = 10; // A tag you can use without having to declare a new variable
B.x = 10; // Does not work
B bb; // Because 'B' is an alias, you have to declare a new variable
bb.x = 10;
The example bellow just change structfor union, work the same way.
下面的示例只是更改struct为union,以相同的方式工作。
struct a { int x; }; // Regular complete struct type
typedef struct a aa; // Alias 'aa' for the struct 'a'
struct { int x; } b; // Tag 'b'
typedef struct b bb; // Compile, but unusable.
struct c { int x; } C; // identifier or struct name 'c' and tag 'C'
typedef struct { int x; } d; // Alias 'd'
typedef struct e { int x; } ee; // struct 'e' and alias 'ee'
回答by theJPster
Another solution is to put the common header value (enum node_type type) into every structure, and make your top-level structure a union. It's not exactly "Don't Repeat Yourself", but it does avoid both anonymous unions and uncomfortable looking proxy values.
另一种解决方案是将公共标头值 ( 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;
}
回答by jer
Looking at 6.2.7.1 of C99, I'm seeing that the identifier is optional:
查看 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
I've been up and down searching, and cannot find any reference to anonymous unions being against the spec. The whole -opt suffix indicates that the thing, in this case identifieris optional according to 6.1.
我一直在上下搜索,找不到任何关于匿名工会违反规范的参考。整个 -opt 后缀表示事物,在这种情况下identifier,根据 6.1 是可选的。
回答by Svisstack
Union must have a name and be declared like this:
Union 必须有一个名字并像这样声明:
union UPair {
struct int_node int_n;
struct double_node double_n;
};
UPair X;
X.int_n.value = 12;

