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

C中的结构和联合,确定大小和访问成员,c,structure,unions,C,Structure,Unions,全部, 这里有一个关于工会的例子,我觉得很困惑 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 do

全部,

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

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}?我很困惑,因为在联合包装的结构


另外,如何访问结构中的变量
d
<代码>变量d?

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

您正在使用标准的扩展。在ISO C中,将无法访问内部结构。但在GCC(我相信MSVC)中,您可以执行
var.d


另外,您缺少内部结构后面的分号。

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

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

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

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

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

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


有关编译时断言技巧的讨论,请参见其他内容。

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

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


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

你不能确定,因为编译器可以填充这些结构以实现更好/正确的数据对齐。但是填充是程序员需要提及的一个选项,对吗?如果代码按照上面的方式编译,内存布局会是什么?否,默认情况下编译器可以(通常会)插入填充。根据标准,填充是实现定义的。根据我的经验,有些(大部分)提供了一种控制它的方法,但标准只要求实现者记录将使用什么填充。结构的第一个元素的偏移量是0,意味着指向结构实例的指针可以被安全地转换为它的第一个元素的指针(反之亦然)。“考虑到字符是1个字节”=> char总是不存在实现1,你可能会注意到这个问题被标记为C,而不是C++。是的,这是一种罕见的情况,OP实际上正确地识别了该语言,而不是谈论一些虚构的C/C++混合语言。在任何情况下,他都在询问C语言,而类和保护不是C语言的特性。