当我打印像这样的联盟的大小时:
union u {
char c[5];
int i;
} un;
使用:
int _tmain(int argc, _TCHAR* argv[])
{
printf("size of union = %d ",sizeof(un));
return 0;
}
我使用Visual C ++得到了8的答案,但我预计5.为什么?
嗯,对于同样的例子, 我做了这样的事情:
int i1 = 0x98761234;
un.i = i1;
printf("\n un.c[0] = %x ",un.c[0]);
printf("\n un.c[1] = %x ",un.c[1]);
printf("\n un.c[2]= %x ",un.c[2]);
printf("\n un.c[3] = %x ",un.c[3]);
printf("\n un.c[4] = %x ",un.c[4]);
printf("size of union = %d ",sizeof(un));
我得到了像
这样的结果un.c[0] = 34;
un.c[1] = 12;
un.c[2] = 76;
un.c[3] = ffffff98;
为什么在un.c [3]
有6fs答案 0 :(得分:11)
sizeof
运算符生成变量或类型的大小,包括分隔该类型数组中元素所需的任何填充,以便所有内容仍然正确对齐。由于你的联盟有一个int
成员,它需要4字节对齐,所以它的“自然”大小会向上舍入到下一个4字节的倍数。
ffffff98
是因为您正在使用已签名的char
进行编译。将%x
与非unsigned int
的参数一起使用会导致未定义的行为;你所看到的有时被称为 sign-extension 。您将别名的结果0x98
重新解释为char
,即-104
。这保留了升级到int
的价值(这称为默认参数促销),当-104
别名为unsigned int
时,0xffffff98
为{{1}} }}。
答案 1 :(得分:3)
你的联盟的对齐必须是其任何成员的最大对齐。这是4.因此,联合的大小必须与该大小对齐。它本来可以是5(因为c
是联合中最大的成员),但是由于整个联合的对齐是4,所以联合的大小填充为8。
请注意,这仅适用于VC ++。该标准没有特别要求。虽然它确实允许实现根据需要填充类型,VC ++会这样做。 GCC可以做一些不同的事情,可以使用编译时开关来改变这种行为。
答案 2 :(得分:3)
编译器为对齐添加了几个字节
答案 3 :(得分:1)
编译器可以在任何想要结构,联合和类的地方添加填充来加速内存访问。你正在看到它的影响。对于Visual C ++,填充通常是最大成员类型大小的倍数。在这个例子中,最大的成员是一个int,因此它用3个未使用的字节填充联合,使总大小为8。
答案 4 :(得分:0)
感谢您的建议。我尝试了很多例子并且看起来如此 联合大小相当于 (最大元素的大小)+填充(取决于所使用的最高数据类型的大小)。