简体   繁体   English

C数组可以在元素之间包含填充吗?

[英]Can C arrays contain padding in between elements?

I heard a rumor that, in C, arrays that are contained inside structs may have padding added in between elements of the array. 我听说有传言说,在C中,包含在结构中的数组可能在数组的元素之间添加了填充。 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) . 我很确定sizeof(values)总是等于sizeof(foo.values) However, I have not been able to find anything in the C standard (specifically C99) that explicitly confirms or denies this. 但是,我无法在C标准(特别是C99)中找到明确证实或否认这一点的任何内容。

Does anyone know if this rumor is addressed in any C standard? 有谁知道这个谣言是否在任何C标准中得到解决?

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 . 编辑 :我知道数组foo.values的结尾和struct foo的结尾之间可能存在填充,并且标准声明foo的开头和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 ? 但是,是否有人引用引用标准,其中foo.values的元素之间没有填充?

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...". C99标准调用数组类型“数组类型描述了连续分配的非空对象集......”。 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. 编译器可能会这样做以帮助对齐结构,但C标准没有说明这一点。

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 and foo.values arrays will have the same size. 在您的示例中, valuesfoo.values数组将具有相同的大小。 Any padding will be part of the struct foo instead. 任何填充都将成为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 type struct foo * , then 可能需要尾随填充字节,因为直接在结构上的内存位置也必须符合结构的对齐要求,即如果bar的类型为struct foo * ,则

(struct foo *)((char *)bar + sizeof(struct foo))

yields a valid pointer to struct foo (ie doesn't fail due to mis-alignment). 产生一个指向struct foo的有效指针(即由于未对齐而不会失败)。

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. 这适用于结构中包含的数组:如果数组的第一个元素正确对齐,则所有后续元素也是如此。

Yes, sort of. 是的,有点。 Variables are often aligned to some boundry, depending on the variable. 变量通常与某些边界对齐,具体取决于变量。 Take the following, for instance: 举例来说,例如:

typedef struct
{
    double d;
    char c;
} a_type_t;

double and char are 8 and 1 bytes, on my system, respectively. 在我的系统上,double和char分别是8和1个字节。 Total of 9. That structure, however, will be 16 bytes, so that the doubles will always be 8-byte aligned. 总共9.然而,该结构将是16个字节,因此双精度数将始终是8字节对齐的。 If I had just used ints, chars, etc, then the alignment might be 1, 2, 4, or 8. 如果我刚使用了int,chars等,那么对齐可能是1,2,4或8。

For some type T, sizeof(T) may or may not equal sizeof(Ta) + sizeof(Tb) + sizeof(Tc) ... etc. 对于某些类型T, sizeof(T) 可能等于或不等于 sizeof(Ta) + sizeof(Tb) + sizeof(Tc) ...等。

Generally, this is entirely compiler and architecture dependent. 通常,这完全取决于编译器和体系结构。 In practice, it never matters. 在实践中,它永远不重要。

Consider: 考虑:

struct {
  short s;
  int i;
} s;

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. 假设短路是16位而你是32位,则大小可能是8字节,因为每个结构成员往往对齐一个字(在这种情况下为32位)边界。 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. 值得强调的是,这是不一定由C标准定义的实现行为。 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). 非常类似于短裤,整数和多头(C标准只是说短裤不会比整数更大,而且多头也不会小于整数,最终可能会达到16/32 / 32,16 / 32/64 ,32/32/64或许多其他配置)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM