代码之家  ›  专栏  ›  技术社区  ›  Kishore Suresh

C/C中字符数组的填充++

  •  -2
  • Kishore Suresh  · 技术社区  · 2 年前

    互联网上的多个来源,包括 this question 在Stackoverflow中,建议在C中的数组元素之间永远不会有任何填充。

    然而,根据 2nd Edition of Compilers: Principles, Techniques, and Tools ,第428页(逻辑)或第453页(物理):

    在许多机器上,添加整数的指令可能要求整数对齐,即放置在可被4整除的地址。尽管长度为10的字符数组(如C)只需要足够的字节来容纳10个字符,但编译器可以分配12个字节来获得正确的对齐,而不使用2个字节。

    为了验证这一点,我编写了一个小型C++程序来打印char数组元素的地址,并且没有填充。

    编辑:我的问题是,数组元素之间是否会存在填充。答案解释说,书中提到的填充将位于数组的末尾。谢谢

    0 回复  |  直到 2 年前
        1
  •  3
  •   John Bollinger    2 年前

    尽管长度为10的字符数组(如C)只需要足够的字节来容纳10个字符,但编译器可以分配12个字节来获得正确的对齐,而不使用2个字节。

    这是一个误导性的说法。如果在文件范围内声明

    int before;
    char my_array[10];
    int after;
    

    则阵列的大小为10。时期编译器可能会在的存储之前或之后留下未分配的空间 my_array ,但这由编译器自行决定,并且 这样的额外空间不是数组的一部分 (在这种情况下,我通常不会把它称为“填充”,而是YMMV)。

    如果声明包含数组的结构:

    struct my_struct {
        int before;
        char my_array[10];
        int after;
    }
    

    那么编译器可以在结构之间进行填充布局 my_array after ,但是阵列的大小仍然是10。填充属于结构,而不属于数组。

    类似的情况也适用于元素类型本身具有大于1字节的对齐要求的数组。可以指定数组的开头,以便之前有未使用的空间,但该空间不是数组的一部分。

    为了验证这一点,我编写了一个小型C++程序来打印char数组元素的地址,并且没有填充。

    同一数组的元素之间肯定不会有填充。C和C++都非常清楚这一点,你引用的源代码并没有说其他的。

        2
  •  2
  •   Shaurya Singh    2 年前

    您所指的问题与结构填充有关,而不是C或C++中数组元素之间的填充。在这种情况下,填充是指在结构成员之间插入未使用的字节,以便在内存中正确对齐它们。

    在数组的情况下,元素被连续存储在内存中,它们之间没有任何填充。每个元素占用其数据类型所需的确切空间量。

    你在书中提到的那段话“ 编译器:原理、技术和工具 “正在讨论结构填充,它与数组没有直接关系。在处理结构时,编译器可能会在成员之间插入填充字节,以根据目标机器体系结构的对齐要求进行对齐。这种对齐可以提高性能,因为某些处理器可能对某些数据类型有对齐限制。

        3
  •  1
  •   Eric Postpischil    2 年前

    您引用的文本谈到(a)某些整数类型所需的对齐方式,以及(b)字符数组后的填充。提到两种不同的类型表明填充不是针对字符数组的,而是针对某个整数类型的。这方面的线索在你引用之前的一段中,它的结尾是:

    集合门类型(如阵列或结构)的存储空间必须足够大,可以容纳其所有组件。

    因此,引用可能会讨论聚合中的填充。字符数组本身不需要任何填充,但如果它在一个也具有整数类型的结构中,则可能需要在字符数组之后进行填充,以便该结构的下一个成员具有所需的对齐(或者整个结构具有使其大小为其成员的对齐要求的倍数所需的大小)。引用也可能是在讨论通常放置多个对象,例如排列编译器将放置在堆栈空间或其他存储中的几个对象。