3

全部,

这是一个关于工会的例子,我觉得很困惑。

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

考虑到char是 1 个字节,int是 2 个字节和long4 个字节。这里整个结构的大小是多少?联合大小会是 {size of char*}+ {size of double} 吗?由于联合中包裹的结构,我感到困惑。

另外,如何访问d结构中的变量。 var.d?

4

3 回答 3

5

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

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

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

于 2010-07-31T23:07:52.720 回答
1

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

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

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

编辑:一般来说,由于所有成员类型的大小本身都是实现定义的,而填充是实现定义的,因此您需要参考您的实现和平台的文档才能确定。

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

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

有关编译时断言技巧的讨论,请参见this question 。

于 2010-07-31T23:21:10.447 回答
-3

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

几年前,我们有一个开发人员喝了 union 的 koolaid,并将其放入他所有的数据结构中。结果,他用它编写的功能现在是我们整个应用程序中最受鄙视的部分之一,因为它们是不可修改、不可修复和不可理解的。

此外,Union 抛弃了现代 c/c++ 编译器为您提供的所有类型安全性。当然,如果你对编译器撒谎,它总有一天会报复你。实际上,当您的应用程序崩溃时,它会返回给您的客户。

于 2010-08-01T03:05:22.533 回答