为什么我的工会规模比我预期的要大?
当我像这样打印联合的大小时:
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
When I print the size of a union like this:
union u {
char c[5];
int i;
} un;
using this:
int _tmain(int argc, _TCHAR* argv[])
{
printf("size of union = %d ",sizeof(un));
return 0;
}
I get an answer of 8 using Visual C++, but I expected 5. Why?
Well, for the same example,
i did something like this:
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));
i got results like
un.c[0] = 34;
un.c[1] = 12;
un.c[2] = 76;
un.c[3] = ffffff98;
why are there 6fs at un.c[3]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
sizeof
运算符生成变量或类型的大小,包括分隔该类型数组中的元素所需的任何填充,以便所有内容仍然正确对齐。由于您的联合有一个int
成员,因此它需要 4 字节对齐,因此其“自然”大小会向上舍入到下一个 4 字节的倍数。ffffff98
是因为您正在使用签名的char
进行编译。将%x
与非unsigned int
参数一起使用会导致未定义的行为;您所看到的有时称为符号扩展。别名的结果是0x98
重新解释为char
,即-104
。这在提升为int
时保留其值(这称为默认参数提升),并且在别名为时保留 int
变为-104
>unsigned int0xffffff98
。The
sizeof
operator produces the size of a variable or type, including any padding necessary to separate elements in an array of that type such that everything is still correctly aligned. Since your union has anint
member, it needs to be 4-byte aligned, so its "natural" size gets rounded upwards to the next multiple of 4 bytes.The
ffffff98
is because you're compiling with signedchar
. Using%x
with an argument that is notunsigned int
causes undefined behaviour; what you're seeing is sometimes called sign-extension. The result of your aliasing is0x98
reinterpreted aschar
, which is-104
. This retains its value on being promoted toint
(this is called the default argument promotions), and the int-104
when aliased asunsigned int
becomes0xffffff98
.您的工会的联盟必须是其所有成员中最大的联盟。这是 4。因此,联合的大小必须与该大小对齐。它本来可以是 5(因为
c
是联合体中最大的成员),但由于联合体整体的对齐方式是 4,因此联合体的大小被填充为 8。请注意,仅适用于 VC++。标准没有特别要求。尽管它确实允许实现根据需要填充类型,VC++ 就是这样做的。 GCC 可以做一些不同的事情,并且您可以使用编译时开关来改变这种行为。
The alignment of your union must be the largest alignment of any of its members. This is 4. Therefore, the size of the union must be aligned to that size. It could have been 5 (as
c
is the largest member of the union), but because the alignment of the union as a whole is 4, the size of the union is padded to 8.Note that this is just for VC++. The standard does not specifically require it. Though it does allow implementations to pad types as needed, which VC++ does. GCC could do something different, and there could be compile-time switches you could employ to change this behavior.
编译器可以在结构体、联合体和类中的任意位置添加填充,以加速内存访问。你正在看到它的效果。对于 Visual C++,填充通常是最大成员类型大小的倍数。在本例中,最大的成员是 int,因此它用 3 个未使用的字节填充联合,使总大小为 8。
The compiler can add padding wherever it wants to structs, unions, and classes to speed memory accesses. You are seeing the effect of that. For Visual C++, the padding is usually a multiple of the size of the largest member type. In this instance, the largest member is an int, therefore it pads the union with 3 unused bytes to make the total size 8.
感谢您的建议。我尝试了很多例子,看起来
联合大小等于
(最大元素的大小)+填充(取决于使用的最高数据类型的大小)。
Thanks for your suggestions. I tried this with a lots of examples and looks that
union size is equivalent to
(size of max element)+ padding(depending upon the size of highest datatype used).