C 访问结构并集中结构的第一个字段
我有三个结构共享第一个字段的第一种类型和名称:C 访问结构并集中结构的第一个字段,c,struct,unions,memory-alignment,pointer-conversion,C,Struct,Unions,Memory Alignment,Pointer Conversion,我有三个结构共享第一个字段的第一种类型和名称: 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*/ }; 如果我没记错的话,结构的第一个字段必须从与结构本身相同的地址开始 这让我想
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);
关于这一点,我有两个问题:
struct
或union
的第一个元素保证与struct´/
union本身具有相同的地址值。显然它不是同一类型的
对于您的使用,您不需要强制转换,实际上应该避免:
6.5.2.3p6:为简化联合的使用,我们提供了一项特殊保证:如果联合包含多个共享相同初始序列的结构(见下文),并且联合对象当前包含其中一个结构,允许在任何地方检查任何接头的公共初始部分,以确保接头完整类型的声明可见
所以你可以(见下文)简单地
(注意:您对未命名的union
成员的使用不是标准编译器。它是一个(非常有用的)gcc扩展(-fms extensions
,至少MSVC也支持它)。)
但是:你问题中的代码是错误的。您必须为每个联合成员命名,或者为每个成员指定类型声明符。但是,对于同一个第一个成员,它将不起作用,因为这些未命名成员的成员名称必须是唯一的(否则如何单独访问它们?)。所以这不会真正起作用。你能做的是:
union data {
struct TYPEA typea;
struct TYPEB typeb;
struct TYPEC typec;
};
及
即使struct
当前包含TYPEB
的值
另一种更清晰的方法是将
联合
包装到结构中
:
struct TypeA {
int x,y;
};
...
struct data {
char *name;
union {
struct TypeA;
struct TypeB;
struct TypeC;
};
};
这也在两个级别上使用了gcc扩展:外部结构
和联合
。因此,所有可能的路径都需要唯一的名称。如果希望100%兼容,请按上述方式命名每个成员,并在访问时使用完整路径
注意:我从
union
中的内部struct
s中删除了name
成员,并将其移动到外部struct
。我还改了名字。C中唯一被广泛接受的命名约定是仅对宏使用所有大写。C中没有“通用约定”。如果该标准不能保证某些内容,则取决于实现或使用UB。标准确实保证了这一点。真正的问题是:你为什么在乎?演员阵容是个坏主意。使用第一个元素。更好:将普通成员移动到包含的结构
@Olaf是的,我想我在考虑具体实现是如何实现的;但是因为我对标准感兴趣,我就把它删除了。如果没有它,应该更清楚,谢谢。请下层选民解释一下他们的立场好吗?这是今天要问的比较好的C问题之一,伊姆霍。@Bathsheba:这是我不得不承认我投了错误票的少数几个场合之一。我最初认为它太宽泛了(主要是因为现在删除了部分),但在研究了我自己的问题后,看到你的答案,我认为这确实是一个很好的问题。我现在把向下的一票改为向上的一票。对不起,我错了。谢谢你的回答;我仍然是一个初学者,我试图探索类型系统:)可能不相关,但我发现C类型系统非常有趣;我第一次学习C是在我的数学学士学位上,然后转向函数型和依赖型语言,最后通过Rust回到C;这有点冒险,但也很有启发性。
printf("%s", p->typea.name);
struct TypeA {
int x,y;
};
...
struct data {
char *name;
union {
struct TypeA;
struct TypeB;
struct TypeC;
};
};