C 数组可以在元素之间包含填充吗?
我听说有传言说,在 C 中,包含在结构内部的数组可能在数组元素之间添加了填充。 现在显然,任何一对元素之间的填充量都不能变化,或者使用简单的指针算术不可能计算数组中的下一个元素。
该谣言还指出,不包含在结构中的数组保证不包含填充。 我至少知道那部分是真的。
因此,在代码中,谣言是:
{
// Given this:
struct { int values[20]; } foo;
int values[20];
// This may be true:
sizeof(values) != sizeof(foo.values);
}
我非常确定 sizeof(values)
将始终等于 sizeof(foo.values)
。 然而,我在 C 标准(特别是 C99)中找不到任何明确证实或否认这一点的内容。
有谁知道这个谣言是否在任何 C 标准中得到解决?
编辑:我知道数组 foo.values
的末尾和结构 foo
的末尾之间可能存在填充,并且标准声明在 foo
的开头和 foo.values
的开头之间不会有填充。 然而,是否有人有一个引用或参考标准,其中说foo.values
的元素之间没有填充?
I heard a rumor that, in C, arrays that are contained inside structs may have padding added in between elements of the array. Now obviously, the amount of padding could not vary between any pair of elements or calculating the next element in an array is not possible with simple pointer arithmetic.
This rumor also stated that arrays which are not contained in structures are guaranteed to contain no padding. I know at least that part is true.
So, in code, the rumor is:
{
// Given this:
struct { int values[20]; } foo;
int values[20];
// This may be true:
sizeof(values) != sizeof(foo.values);
}
I'm pretty certain that sizeof(values)
will always equal sizeof(foo.values)
. However, I have not been able to find anything in the C standard (specifically C99) that explicitly confirms or denies this.
Does anyone know if this rumor is addressed in any C standard?
edit: I understand that there may be padding between the end of the array foo.values
and the end of the struct foo
and that the standard states that there will be no padding between the start of foo
and the start of foo.values
. However, does anyone have a quote from or reference to the standard where it says there is no padding between the elements of foo.values
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
不,数组元素之间永远不会有填充。 这是明确不允许的。 C99 标准将数组类型称为“数组类型描述了连续分配的非空对象集...”。 相比之下,结构是“顺序”分配的,而不是“连续”分配的。
结构中的数组之前或之后可能有填充; 那完全是另一种动物。 编译器可能会这样做以帮助结构对齐,但 C 标准对此没有任何说明。
No, there will never be padding in between elements of an array. That is specifically not allowed. The C99 standard calls array types "An array type describes a contiguously allocated nonempty set of objects...". For contrast, a structure is "sequentially", not "contiguously" allocated.
There might be padding before or after an array within a structure; that is another animal entirely. The compiler might do that to aid alignment of the structure, but the C standard doesn't say anything about that.
这里要小心。 填充可以添加在结构的末尾,但不会添加在数组的元素之间,正如您在问题中所述。 数组将始终引用连续的内存,尽管结构数组可能会向每个元素添加填充作为结构本身的一部分。
在您的示例中,
values
和foo.values
数组将具有相同的大小。 任何填充都将成为 struct foo 的一部分。Careful here. Padding may be added at the end of the struct, but will not be added between the elements of the array as you state in your question. Arrays will always reference contiguous memory, though an array of structures may have padding added to each element as part of the struct itself.
In your example, the
values
andfoo.values
arrays will have the same size. Any padding will be part of the structfoo
instead.以下是关于为什么结构可能需要在其成员之间甚至在其最后一个成员之后进行填充,以及为什么数组不需要填充的解释:
不同的类型可能有不同的对齐要求。 某些类型需要在字边界上对齐,其他类型需要在双字甚至四字边界上对齐。 为了实现这一点,结构可以在其成员之间包含填充字节。 可能需要尾部填充字节,因为直接位于结构体中的内存位置也必须符合结构体的对齐要求,即如果
bar
的类型为struct foo *
,则生成指向
struct foo
的有效指针(即不会由于未对齐而失败)。由于数组的每个“成员”都有相同的对齐要求,因此没有理由引入填充。 这对于结构中包含的数组也适用:如果数组的第一个元素正确对齐,则所有后续元素也正确对齐。
Here's the explanation as to why a structure may need padding between its members or even after its last member, and why an array doesn't:
Different types might have different alignment requirements. Some types need to be aligned on word boundaries, others on double or even quad word boundaries. To accomplish this, a structure may contain padding bytes between its members. Trailing padding bytes might be needed because the memory location directly ofter a structure must also conform to the structure's alignment requirements, ie if
bar
is of typestruct foo *
, thenyields a valid pointer to
struct foo
(ie doesn't fail due to mis-alignment).As each 'member' of an array has the same alignment requirement, there's no reason to introduce padding. This holds true for arrays contained in structures as well: If an array's first elment is correctly aligned, so are all following elements.
是的,有点像。 变量通常与某个边界对齐,具体取决于变量。 以以下情况为例:
在我的系统上,double 和 char 分别是 8 和 1 字节。 总共 9 个。但是,该结构将是 16 个字节,因此双精度数始终是 8 字节对齐的。 如果我刚刚使用了整数、字符等,则对齐方式可能是 1、2、4 或 8。
对于某些类型 T,
sizeof(T)
可能等于也可能不等于< /em>sizeof(Ta) + sizeof(Tb) + sizeof(Tc) ...
等。通常,这完全取决于编译器和体系结构。 实际上,这并不重要。
Yes, sort of. Variables are often aligned to some boundry, depending on the variable. Take the following, for instance:
double and char are 8 and 1 bytes, on my system, respectively. Total of 9. That structure, however, will be 16 bytes, so that the doubles will always be 8-byte aligned. If I had just used ints, chars, etc, then the alignment might be 1, 2, 4, or 8.
For some type T,
sizeof(T)
may or may not equalsizeof(T.a) + sizeof(T.b) + sizeof(T.c) ...
etc.Generally, this is entirely compiler and architecture dependent. In practice, it never matters.
考虑一下:
假设 Shorts 是 16 位,而您使用的是 32 位,则大小可能为 8 字节,因为每个结构成员倾向于与字(在本例中为 32 位)边界对齐。 我说“可能”是因为它是特定于实现的行为,可以通过编译器标志等来改变。
值得强调的是,这是 C 标准不一定定义的实现行为。 很像 Shorts、Ints 和 Longs 的大小(C 标准只是说 Shorts 不会大于 Ints,Long 不会小于 Ints,最终可能为 16/32/32、16/32/64 、32/32/64 或许多其他配置)。
Consider:
Assuming shorts are 16 bits and you're on 32 bits, the size will probably be 8 bytes as each struct members tends to be aligned a word (32 bit in this case) boundary. I say "probably" because it is implementation specific behaviour that can be varied by compiler flags and the like.
It's worth stressing that this is implementation behaviour not necessarily defined by the C standard. Much like the size of shorts, ints and longs (the C standard simply says shorts won't be larger than ints and longs won't be smaller than ints, which can end up as 16/32/32, 16/32/64, 32/32/64 or a number of other configurations).