我试图给这个答案提供一个“逻辑上”的反例,表明根据结构体成员的大小对其进行排序将最小化填充时遇到了我认为不合逻辑的情况。
如预期,由于填充,
我的理解是,
为什么编译器不通过将 c 放在 a 的填充位置来最小化填充?
补充:我知道
我唯一能想到的可能是问题的是,如果进行上述优化,则
想象一下以下结构:
struct A
{
int32_t a;
int16_t b;
};
sizeof
这个结构体通常会填充为8个字节,以确保例如在struct A
数组中对齐a
。
现在想象一下这些其他的结构体:
struct B
{
struct A a, b;
int16_t c, d;
};
struct C
{
struct A a;
int16_t c;
struct A b;
int16_t d;
};
如预期,由于填充,
struct B
的大小为20。然而,我本来希望struct C
的大小为16,因为可以避免填充,但是ideone和gcc(有或没有优化)都给出了24字节的大小,显然在每个成员后面填充了2个字节。我的理解是,
struct A
实际上只有6个字节,应该在必要时进行填充,例如在struct B
数组中或在struct B
中使用。但是,在struct C
中,struct A
的填充是不必要的,c
可以放在a
的填充位置,并且d
也可以放在b
的填充位置。为什么编译器不通过将 c 放在 a 的填充位置来最小化填充?
补充:我知道
sizeof(struct A)
必须返回8。否则,memset(array_of_A, 0, N * sizeof *array_of_A)
之类的语句将无法正常工作,因为array_of_A
将包含填充,而N * sizeof *array_of_A
将忽略填充。我唯一能想到的可能是问题的是,如果进行上述优化,则
sizeof(struct C)
将小于其所有成员的sizeof
。但是,我想不出会出现这种情况的用例(即基于未定义行为的用法)。
sizeof(foo.a)
不需要与sizeof(struct A)
不同。当然,如果sizeof(foo.a)
返回8,则它包含其填充中的foo.c
,但您无法访问该部分,因为它在结构体之外,并且访问它将是未定义的行为。那么,如果sizeof(foo.a)
返回8会有什么问题呢? - Shahbaz