【发布时间】:2013-11-16 15:53:37
【问题描述】:
我试图给this answer 提供一个“合乎逻辑”的反例,表明当我遇到在我看来不合逻辑的情况时,根据它们的大小对结构的成员进行排序会最小化填充。
想象以下结构:
struct A
{
int32_t a;
int16_t b;
};
sizeof 这个结构通常会被填充到 8 个字节,以确保 a 对齐,例如在 struct 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 A 的数组中或其在 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() 在同一类型上返回不同的值。例如,sizeof(foo.A) 与 sizeof(struct A) 不同。所以复制这些东西真的很困难。
-
为什么不重新排列成员?因为 C 编译器最初并不是为此而设计的。它是按照您声明它们的顺序排列的。 C 是一种相当低级的语言,让我们可以更好地控制很多事情,如果编译器改变了事情会很糟糕。如果我声明成员
A、B和C,我希望它们按顺序排列在内存中。 -
@CharlieBurns,我的最后一段试图解决这个问题。
sizeof(foo.a)不需要与sizeof(struct A)不同。当然如果sizeof(foo.a)返回8,那么它的填充中包含foo.c,但是你不能访问该部分,因为它在结构之外并且访问它是未定义的行为。那么,如果sizeof(foo.a)返回 8 会有什么问题呢? -
@JeffMercado,我不是要求编译器重新排序成员。该标准明确禁止(C11,6.7.2.1.6)
-
不会 memcpy(&someC.a, &someA, sizeof(someC.a)) 覆盖 someC.c 吗?我想这与答案相同,以及我的评论所要表达的意思。
标签: c