大家好,
我想知道联合(union)是否使用填充(padding)?
由于联合体的大小等于最大数据成员的大小,所以最后是否可能存在填充?
由于联合体的大小是最大数据成员的大小
这并不一定正确。考虑以下例子:
union Pad {
char arr[sizeof (double) + 1];
double d;
};
那个联合体中最大的成员是arr
。但通常情况下,double
会在四个或八个字节的倍数上对齐(取决于架构和double
的大小)。在某些架构上,这甚至是必要的,因为它们不支持未对齐读取。sizeof (union Pad)
通常比sizeof (double) + 1
更大[在64位系统上,通常为16 = 2 * sizeof (double)
,在32位系统上可能为16或12(在具有8位char
和64位double
的32位系统上,double
所需的对齐方式仍可能只有四个字节)]。union
的大小将是不小于最大成员的任何要求的最大对齐方式的最小倍数。double
和union Pad
的大小,以检查编译器是否插入了填充。在64位系统上,我从gcc和clang中都得到了联合体大小是double
大小的两倍(16 = 2 * 8),这是预期的结果。填充的原因是对齐(双方都将double
对齐到8字节边界)。 - Daniel Fischerdouble d
替换为 char d[sizeof(double)]
,则联合体不会填充。(至少在linux/gcc下) - ideasman42char
的对齐方式是1。如果你使用int d[2]
,你可能会得到12作为大小,因为现在int
通常是四个字节,并且有四个字节的对齐方式。(除了在嵌入式系统上,它可能经常是两个字节。) - Daniel Fischer当我们在其中使用原始类型时,Union
union
{
char c;
int x;
}
看起来它没有使用填充,因为最大尺寸的数据总是对齐到边界。
但是当我们在联合体中嵌套结构时,它会使用填充。
union u
{
struct ss
{
char s;
int v;
}xx;
}xu;
这导致大小为8。
所以你的问题的答案是UNION中存在PADDING。
int
大小的倍数,即4个字节。因此,除非您使用#pragma pack(1)
,否则大小为3个字节的联合体将填充一个额外的字节以产生4个字节。在发布问题之前,请编写一个程序并尝试一下。 - Rüppell's Vulturepadding
总是会被执行?就像Daniel Fischer所说,这并不是标准要求的。 - Rüppell's Vulture#pragma pack(1)
,那么它将占用3个字节。 - Rüppell's Vulture