提问人:Neeraj-Kumar-Coder 提问时间:1/30/2021 最后编辑:brucegNeeraj-Kumar-Coder 更新时间:2/2/2021 访问量:58
为什么无论成员的顺序如何,这种结构的大小都是相同的?
Why the size of this structure is same irrespective of the order of the members?
问:
由于 C 中结构的内存对齐是以连续的形式完成的,首先是第一个元素,然后是第二个元素,然后是第三个元素,依此类推......除了位填充,那么为什么即使重新排列元素,这个结构的大小也是一样的:
#include <stdio.h>
int main(void)
{
struct student
{
float c;
int a;
char b;
};
printf("%zu\n", sizeof(struct student));
return 0;
}
输出:12
对于上述结构配置,内存对齐是否如下所示?
f f f f i i i i c
_ _ _ _ _ _ _ _ _ _ _
0 1 2 3 4 5 6 7 8 9 10
答:
在系统上,和 数据类型的大小似乎为 4 个字节;因此,编译器(除非另有说明)将在 4 字节边界上对齐这些类型的结构成员。这就是为什么,如果您将该字段作为第二个成员,则将在该字段和下一个字段之间添加 3 个字节的“填充”,从而为结构提供 12 个字节的总大小。int
float
char b
但是,编译器也会在结构的末尾添加填充!(同样,在最后一个字段是 when 的情况下,三个字节。char b
为什么?好吧,考虑一个这样的类型的数组。如果没有这种“终端填充”,第二个数组元素的第一个字段将错位——也就是说,它不会在 4 字节边界上,从而降低从“内部”填充中获得的任何效率。对于将类型作为嵌套字段包含的其他结构,也会出现类似的问题。struct
编辑:我无法真正对此维基百科页面上的以下声明提供太多改进:
需要注意的是,最后一个成员用数字填充 所需的字节数,因此结构的总大小应为 任何结构构件的最大对齐的倍数......
评论
struct
struct sample { char b; int a; char c; };
12
b
c
struct sample { char b; char c; int a; };
c
char
似乎在您的机器上,每个都需要 4 个字节。从这个意义上说,它们在中的位置是无关紧要的。int
float
struct
但是,a (通常)只需要 1 个字节,所以您可能想知道为什么 come 不返回 (4+4+1),原因是填充。char
sizeof
9
在许多情况下都会添加填充,但最明显的是允许类型对齐(我假设系统上的 and 类型在 4 字节边界上自然对齐)。int
float
我认为如果将顺序更改为:
struct student
{
float c;
char b;
int a;
};
在此示例中,我们将有 4 个字节 () + 1 个字节 () + 3 个字节(填充)+ 4 个字节 ()。即:float
char
int
struct student
{
float c;
char b;
char padding[3];
int a;
};
但是,在原始示例中,我们有:
struct student
{
float c;
int a;
char b;
};
这会产生 4 个字节 () + 4 个字节 () + 1 个字节 () + 3 个字节(填充) - 即:float
int
char
struct student
{
float c;
int a;
char b;
char padding[3];
};
我们仍然在末尾获得填充的原因是允许数组 ()。struct
struct student array[32]
如果末尾没有任何填充,则数组 () 的第二个成员将从偏移量开始,并且类型 () 将无法在自然的 4 字节边界上正确对齐。struct
array[1]
float
声明类型时,编译器将始终添加允许在数组中使用该类型的所需填充(即,在使用 .malloc
我希望这能回答你的问题。
编辑:
为了澄清我上面没有列出的其余部分的填充(参见注释),它可能看起来像这样(假设编译器正在为类似的系统编译代码):struct
struct student
{
char b;
char padding[3];
float c;
int a;
};
如果也是,我们将在以下两端获得填充:a
char
struct
struct student
{
char b;
char padding[3];
float c;
char a;
char padding2[3];
};
但是,如果我们重新组织 字符彼此相邻,它们的填充会有所不同,因为该类型在此系统上没有 4 个字节的自然对齐:struct
char
struct student
{
char b;
char a;
char padding[2];
float c;
};
注意:
大多数编译器应该支持一个指令,告诉编译器“打包”结构(忽略类型对齐和填充)......但是,恕我直言,应该强烈建议不要这样做,因为它可能会导致某些 CPU 架构崩溃并引入不可移植的代码(另请参阅此处)。
评论
struct student { char b; int a; char c; };
12
编译器对齐字段并填充 的其余部分,因此,如果您构建一个数组,下一个元素将对齐。struct
在您发布的案例中,字段元素的对齐方式是两个字段的大小,大小为 4 个字节。因此,编译器在末尾填充结构,以便您定义的类型的下一个数组元素也对齐。这意味着编译器必须在类型化字段之后添加三个 pad 元素,即使它位于结构的末尾。float
int
char
在你发布的情况下,如果你认为结构是 5 个字节,结构数组的下一个元素将不会对齐,因为浮点数和 int 将从对齐的偏移量开始。+1
评论
structure