C中的结构和联合,确定大小和访问成员

所有,

这是一个关于联盟的例子,我觉得这很令人困惑。

struct s1 { int a; char b; union { struct { char *c; long d; } long e; }var; }; 

考虑到char是1个字节, int是2个字节, long是4个字节。 这里整个结构的大小是多少? 联合大小是{size of char *} + {size of double}? 我很困惑,因为在union中包含了struct。

另外,如何访问struct中的变量dvar.d

没有填充,假设sizeof(int)== sizeof(char *)== sizeof(long)== 4,外部结构的大小将为13。

将其分解,union var一个匿名结构重叠为一个long 。 内部结构更大(指针和长)因此它的大小控制联合的大小,使联合消耗8个字节。 其他成员是4个字节和1个字节,因此总数为13。

在我上面做出的大小假设的任何合理实现中,此结构将填充到2字节或4字节边界,向该大小添加至少1或3个额外字节。

编辑:一般情况下,由于所有成员类型的大小本身都是实现定义的,并且填充是实现定义的,因此您需要参考实现文档和平台以确定。

允许实现在结构的基本上任何元素之后插入填充。 合理的实现使用尽可能少的填充来满足平台要求(例如,RISC处理器通常要求值与该值的大小一致)或性能。

如果使用结构将字段映射到文件格式规范所假定的值的布局,共享内存中的协处理器,硬件设备或包装和布局实际上重要的任何类似情况,那么您可能会担心自己是在编译时或运行时测试您对成员布局的假设是否为真。 这可以通过validation整个结构的大小以及其成员的偏移来完成。

有关编译时断言技巧的讨论,请参阅此问题 。

由于填充,大小是实现定义的。 联合将至少是最大成员的大小,而结构将至少是成员大小的总和。 内部结构至少是 sizeof(char *) to sizeof(long) ,所以联合将至少是那么大。 外部结构将至少为sizeof(int) + 1 + sizeof(char *) + sizeof(long) 。 所有结构和联合都可以填充。

您正在使用标准的未命名字段的扩展名。 在ISO C中,无法访问内部结构。 但是在GCC(我相信MSVC),你可以做var.d

此外,您在内部结构后缺少分号。

工会在没有严格纪律的情况下使用是危险且有风险的。 你把它放在一个结构中的事实是非常危险的,因为默认情况下所有的struct成员都是公共的:它暴露了客户端代码对你的union进行更改的可能性,而没有告诉你的程序它在那里填充了什么类型的数据。 如果你使用联盟,你应该把它放在一个类中,至少你可以把它隐藏起来。

几年前,我们开了一个工党,他们喝了工会的koolaid,把它放在他所有的数据结构中。 因此,他用它编写的function现在是我们整个应用程序中最受鄙视的部分之一,因为它们是不可修改的,不可修复的和不可理解的。

Unions还抛弃了现代c / c ++编译器为您提供的所有类型安全性。 当然,如果你撒谎到编译器,它将在某一天回到你的身边。 实际上,当你的应用程序崩溃时,它会回到你的客户手中。