例如,有一个结构
struct A
{
char a;
int i;
};
在这种情况下,我们有 a[1 字节] + 填充[3 字节] + int[4 字节] = 8。
现在让我们对上面的结构进行一些更新,
struct A
{
int i;
char a;
};
在这种情况下,char 在 int 之后,无需添加填充字节,这意味着 sizeof(A) = 5 字节,但在这种情况下,我也得到了 8 字节的结果。为什么?
好的,这个案子呢
struct s
{
int b;
double c;
char a;
};
根据下面给出的逻辑,有一个:size = b[4 bytes] + padding[4 bytes] + c[8] + a[1] + padding[7 bytes to align with double] = 24
,但在执行后我得到 16。这怎么可能?
在这种情况下,
char
int
之后,无需添加填充字节,这意味着sizeof(A) = 5
字节,但在这种情况下,我也得到8
字节的结果。为什么?
首先,您需要了解为什么需要填充?
维基说:
数据结构对齐是在计算机内存中排列和访问数据的方式。它由两个独立但相关的问题组成:数据对齐和数据结构填充。当现代计算机读取或写入内存地址时,它将以字大小的块(例如 32 位系统上的 4 字节块)或更大的方式来执行此操作。数据对齐意味着将数据放在等于字大小的某个倍数的内存偏移量处,由于 CPU 处理内存的方式,这提高了系统的性能。为了对齐数据,可能需要在最后一个数据结构的末尾和下一个数据结构的开头之间插入一些无意义的字节,即数据结构填充。
为了使4
的大小倍数(int
对齐),第二个代码段将填充3
字节。编译后,第二个代码段将被填充以正确对齐
struct A
{
int i;
char a;
char Padding[3]; // 3 bytes to make total size of the structure 8 bytes
};
编辑:永远记住结构填充的这两个黄金法则:
- 仅当结构成员后跟具有较大对齐要求的成员时,或在结构的末尾插入填充。
- 最后一个成员填充所需的字节数,以便结构的总大小应是任何结构成员最大对齐方式的倍数。
在以下情况下
struct s
{
int b;
double c;
char a;
};
对齐将发生为
struct s
{
int b; // 4 bytes. b is followed by a member with larger alignment.
char Padding1[4]; // 4 bytes of padding is needed
double c; // 8 bytes
char d; // 1 byte. Last member of struct.
char Padding2[7]; // 7 bytes to make total size of the structure 24 bytes
};
另请注意,通过更改结构中成员的顺序,可以更改保持对齐所需的填充量。如果成员按降序对齐要求排序,则可以执行此操作。
struct s
{
double c; // 8 bytes
int b; // 4 bytes
char a; // 1 byte. Only last member will be padded to give structure of size 16
};
编译器必须在结构末尾添加填充的原因是结构可以是数组的一部分,并且数组的每个元素都必须正确对齐。
似乎您的平台希望将 int 对齐到 4 个字节。
如果声明struct A
数组:
struct A array[2];
然后,array[1]
的第一个int
成员也应具有 4 个字节的对齐方式。因此,编译器将您的struct A
填充为 8 个字节来完成此操作,而如果它没有添加任何填充并且sizeof(struct A)
是 5 个字节,则array[1]
将无法正确对齐。
(请记住,编译器不能在数组元素之间插入填充,填充必须是数组元素本身的一部分,因为sizeof array
必须与上述情况下的sizeof(struct A) * 2
相同)
不仅struct
的每个成员都必须与数据对齐,而且struct
本身也必须与struct
中最大成员的大小对齐。因此,将填充添加到struct A
,使其大小应该是sizeof i
和sizeof a
较大者的倍数。
在此处查看 C 常见问题解答
如果要有一个结构数组,数组中的所有元素必须具有相同的大小和对齐方式;这意味着对于数组中的事物,大小必须是对齐的倍数。 唯一有用的情况是,如果结构的大小不是对齐的倍数,它没有直接合并到另一个数组中,而是用作另一个结构的一部分。 这种情况有时确实会发生,但还不够频繁,以至于在语言设计中值得特别注意。