Mar*_*tin 49 c gcc struct c99 unions
这里是我所遇到的非常简化的问题代码:
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)兼容?谢谢.
R..*_*R.. 62
匿名联合是GNU扩展,不是任何标准版本的C语言的一部分.对于c99 + GNU扩展,你可以使用-std = gnu99或类似的东西,但最好写出适当的C而不依赖于只提供语法糖的扩展......
编辑:匿名工会在C11中添加,因此它们现在是该语言的标准部分.据推测,GCC -std=c11可以让你使用它们.
bk.*_*bk. 25
我发现这个问题大约在其他人做了一年半之后,所以我可以给出一个不同的答案:匿名结构不符合C99标准,但它们符合C11标准.GCC和clang已经支持这一点(C11标准似乎已经取消了微软的功能,并且GCC已经为一些MSFT扩展提供了一段时间的支持).
好吧,解决方案是命名union的实例(可以作为数据类型保持匿名),然后使用该名称作为代理.
$ 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;
}
现在它编译c99没有任何问题.
$ cc -std=c99 us.c $
注意:无论如何,我对这个解决方案并不满意.
只是为了澄清匿名struct或匿名union。
6.7.2.1 结构和联合说明符
类型说明符是没有标记的结构说明符 的未命名成员称为匿名结构;类型说明符是没有标记的联合说明符的未命名成员称为匿名联合。匿名结构或联合的成员被认为是包含结构或联合的成员。如果包含结构或联合也是匿名的,这将递归地适用。
C99 没有匿名结构体或联合体
简化:类型说明 符标识符 { 声明列表 } 标签 ;
struct或union;structor union;struct和匿名uniontypedef在Type-specifier前面有 a ,则标签是别名而不是标签。只有当它没有标识符和标签,并且存在于另一个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
};
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
下面的示例只是更改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'
Run Code Online (Sandbox Code Playgroud)
Union 必须有一个名称并声明如下:
union UPair {
struct int_node int_n;
struct double_node double_n;
};
UPair X;
X.int_n.value = 12;
Run Code Online (Sandbox Code Playgroud)