代码之家  ›  专栏  ›  技术社区  ›  E.M.

C数组能否在元素之间包含填充?

  •  21
  • E.M.  · 技术社区  · 16 年前

    我听说在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 标准规定在 以及 英尺值 . 但是,有人有没有 引用 参考 表示元素之间没有填充的标准 英尺值 ?

    5 回复  |  直到 9 年前
        1
  •  30
  •   Chris Arguin    16 年前

    不,数组元素之间永远不会有填充。这是特别不允许的。c99标准调用数组类型“数组类型描述了一组连续分配的非空对象…”。相比之下,结构是“顺序的”,而不是“连续的”分配。

    一个结构中的数组前后可能有填充物;这完全是另一种动物。编译器可能这样做是为了帮助结构的对齐,但是C标准没有对此做任何说明。

        2
  •  8
  •   Dan Olson    16 年前

    小心点。填充可以添加到结构的末尾,但不会在问题中所述的数组元素之间添加。数组始终引用连续的内存,尽管一个结构数组可能在每个元素中添加了填充,作为结构本身的一部分。

    在您的示例中, values foo.values 数组大小相同。任何填充都将是结构的一部分 foo 相反。

        3
  •  3
  •   Christoph    16 年前

    这是关于 为什么? 结构可能需要在其成员之间填充,甚至在其最后一个成员之后填充,以及数组不填充的原因:

    不同的类型可能有不同的对齐要求。有些类型需要在单词边界上对齐,另一些类型需要在双甚至四个单词边界上对齐。为了实现这一点,结构的成员之间可以包含填充字节。可能需要尾随填充字节,因为直接位于结构的内存位置也必须符合结构的对齐要求,即如果 bar 属于类型 struct foo * 然后

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

    生成指向的有效指针 struct foo (也就是说,不会因为对齐错误而失败)。

    由于数组的每个“成员”都有相同的对齐要求,因此没有理由引入填充。这对于包含在结构中的数组也适用:如果数组的第一个元素正确对齐,那么下面的所有元素也是如此。

        4
  •  1
  •   Thanatos    16 年前

    是的,差不多。变量通常与某些边界对齐,这取决于变量。举个例子:

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

    在我的系统上,double和char分别是8和1字节。总计9。然而,这个结构将是16个字节,因此双精度数将始终是8字节对齐的。如果我刚刚使用了ints、chars等,那么对齐方式可能是1、2、4或8。

    对于T型, sizeof(T) 可能等于也可能不等于 sizeof(T.a) + sizeof(T.b) + sizeof(T.c) ... 等。

    通常,这完全依赖于编译器和体系结构。实际上,这并不重要。

        5
  •  0
  •   cletus    16 年前

    考虑:

    struct {
      short s;
      int i;
    } s;
    

    假设短裤是16位的,而你是32位的,那么尺寸会 可能 为8字节,因为每个结构成员倾向于对齐一个单词(在本例中为32位)边界。我之所以说“可能”,是因为它是特定于实现的行为,可以通过编译器标志等来改变。

    值得强调的是,这是C标准不一定定义的实现行为。很像短裤、英特和多头的尺寸(C标准简单地说短裤不会比英特大,而多头也不会比英特小,最终可以是16/32/32、16/32/64、32/32/64或其他一些配置)。