2

我知道这个答案违反了reinterpret_cast规则,但它也假定子数组将被线性分配。

我相信这并不能保证,但是当我搜索标准时,我发现我的信心在动摇。如果我静态分配一个二维数组,如下所示:

int foo[][4] = { { 5, 7, 8 },
                 { 6, 6 },
                 {},
                 { 5, 6, 8, 9 } };

我可以假设所有元素都将线性分配吗?也就是说如果foo[0]在地址0x00000042处,会:

  • foo[1]位于地址 0x00000052
  • foo[2]位于地址 0x00000062
  • foo[3]位于地址 0x00000072

sizeof(int) == 4这些地址是十六进制的,是的,它们为带有;的 4 元素子数组提供空间。它们可能也可能不会被零初始化。

4

2 回答 2

5

子数组是否保证线性分配?

是的。无论数组的元素是子数组还是非数组对象,都保证在内存中连续存储。

为了完整起见,以下是标准报价:

[dcl.array]

  1. [snip] 数组类型的对象包含一个连续分配的非空集合,由 N 个 T 类型的子对象组成。 [snip]

T是一个数组时也不例外。


所以我们知道这不能保证是const char[4].

相反,我们确实知道这对对象是有char[4]保证的,就像对其他类型有保证一样。

例如: const char first[] = "foo"; char foo[][4] = {"bar", "foo", "", "baz"}

first将像这样存储在内存中:

{'f', 'o', 'o', '\0'}

foo将像这样存储:

{'b', 'a', 'r', '\0', 'f', 'o', 'o', '\0', '\0', '\0', '\0', '\0', 'b', 'a', 'z', '\0'}

那么为什么你会说这对于整数是有保证的呢?

它是保证的int[4]char[4]以及您可以想象的任何其他类型。

于 2016-06-27T15:04:14.727 回答
3

来自 C 语言标准 ISO/IEC 9899 §6.2.5 Types/p20Emphasis Mine):

数组类型描述了一组连续分配的具有特定成员对象类型的非空对象,称为元素类型。

同样来自 C 语言标准 ISO/IEC 9899 §6.5.2.1/p3 数组下标Emphasis Mine):

连续的下标运算符指定多维数组对象的一个​​元素。如果E是一个维度为 的 n 维数组 (n >= 2) i x j x . . . x k,则E(用作左值以外)将转换为指向维度为 的(n - 1)维度数组的指针j x . . . x k。如果一元运算*符显式地或作为下标的结果隐式地应用于此指针,则结果是指向的(n - 1)维数组,如果用作左值以外的数组,它本身将转换为指针。由此得出,数组以行优先顺序存储(最后一个下标变化最快)。

从上面我们可以得出结论,一个二维数组实际上是一个以行优先顺序存储的一维数组。

因此,可以安全地假设子数组的元素连续存储在内存中

于 2016-06-27T15:23:31.363 回答