我有三个共享第一个字段和第一个字段名称的结构:
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);
我有两个问题:
答案 0 :(得分:2)
struct
或union
的第一个元素保证与struct´/
联合本身具有相同的地址值。显然它的类型不一样!
对于您的使用,您不需要演员表,实际上应该避免使用:
6.5.2.3p6:为了简化联合的使用,我们做了一个特殊的保证:如果一个联合包含几个共享一个共同初始序列的结构(见下文),并且如果联合对象当前包含这些结构中的一个,允许检查其中任何一个的公共初始部分,其中可以看到完整类型的联合的声明。 ...
所以你可以(见下文)
printf("%s", p->name);
(注意:您对未命名的union
成员的使用不是标准的编译。它是(非常有用的)gcc扩展名(-fms-extensions
,至少也得到MSVC的支持)。)< / p>
但是:您问题中的代码是错误的。您必须为每个联合成员命名,或者为每个成员指定类型声明符。但是,如果使用相同的第一个成员,它将不会被打开,因为这些未命名成员的名字必须是唯一的(他们应该如何单独访问它们?)。所以这不会真的奏效。你可以做的是:
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%兼容,请像上面一样命名每个成员并使用访问的完整路径。
注意:我从name
的内部struct
移除了union
成员,并将其移至外部struct
。我也换了名字。 C中唯一被广泛接受的命名约定是仅对宏使用全大写。