我有三个共享第一个字段的类型和名称的结构:
struct TYPEA {
char *name;
int x,y; /*or whatever*/
};
struct TYPEB {
char *name;
float a[30]; /*or whatever*/
};
struct TYPEC {
char *name;
void *w,*z; /*or whatever*/
};
如果我没记错的话,必须在与结构本身相同的地址开始启动结构的第一个字段。
这让我想知道联盟是否相同:
union data {
struct TYPEA;
struct TYPEB;
struct TYPEC;
};
union data *p = function_returning_a_sane_default_for_union_data();
printf("%s", (char*) p);
我有2个问题:
- 是标准要求的工会始终在同一地址上拥有他们的内容?
- 如果结构都具有相同的fiels,仅在名称上有所不同?
struct
或union
的第一个元素保证具有与struct´/
联合本身相同的地址值。显然它没有相同的类型!
对于您的使用情况,您不需要演员表,实际上应该避免使用:
6.5.2.3p6:为了简化工会的使用而做出一种特殊保证:如果联合包含几个共享共同初始序列的结构(请参见下文),以及联合对象当前包含其中一种结构之一,可以在任何地方都可以检查其中的任何一个共同的初始部分,以宣告已完成的工会类型。…
所以您可以(见下文)简单
printf("%s", p->name);
(注意:您对未命名的union
成员的使用不是标准编译剂。它是(非常有用的)GCC扩展(-fms-extensions
,至少也由MSVC支持)。)
但是:问题中的代码是错误的。您必须命名每个联合成员或具有每个成员的类型声明人。但是,对于同一个第一个成员,它不会引起Weork,因为此类不愿透露姓名的成员的名称必须是唯一的(还应该如何单独访问它们?)。因此,这不会真正起作用。您的可以做什么是:
union data {
struct TYPEA typea;
struct TYPEB typeb;
struct TYPEC typec;
};
和
printf("%s", p->typea.name);
即使struct
当前包含TYPEB
的值。
一种替代方法,更清晰的方法是将union
包装到struct
中:
struct TypeA {
int x,y;
};
...
struct data {
char *name;
union {
struct TypeA;
struct TypeB;
struct TypeC;
};
};
这还使用了两个级别的GCC扩展名:对于外部struct
和union
。因此,它需要所有可能的路径的唯一名称。如果您想符合100%的符合条件,请命名每个成员上面的成员,并在访问时使用完整的路径。
注意:我从union
中的内struct
s中删除了name
成员,并将其移至外部struct
。我也更改了名称。C中唯一公认的命名约定是仅将全填充酶用于宏。