子数组是不是保证线性分配? [复制]

Posted

技术标签:

【中文标题】子数组是不是保证线性分配? [复制]【英文标题】:Are Sub-Arrays Guaranteed to be Allocated Linearly? [duplicate]子数组是否保证线性分配? [复制] 【发布时间】:2016-10-29 15:49:39 【问题描述】:

我知道this answer 违反了reinterpret_cast rules,但它也假定子数组将被线性分配。

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

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 元素子数组提供空间;它们可能会也可能不会被零初始化。

【问题讨论】:

如果foo[0] 位于地址0x00000042,则foo[1] 将位于地址0x00000052,仅当sizeof(int)4 时。我怀疑你认为sizeof(int)4 @NathanOliver 这绝对不是骗子,因为他mallocs 内存在一个循环中,所以你绝对不能保证这些子数组在内存中的布局。 @JonathanMee 问题不一样,但答案描述的是静态二维数组而不是动态分配的指针数组。因此我投了反对票。 @RSahu 好的我已经编辑了我认为我已经涵盖了所有基础...... 【参考方案1】:

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

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

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

[dcl.array]

    [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] 和您可以想象的任何其他类型。

【讨论】:

所以我们知道const char[4] 不保证是这种情况。例如:const char first[] = "foo"; char foo[][4] = "bar", "foo", "", "baz" 那你为什么说这是保证ints 的呢? @JonathanMee,如果您使用char foo[][4] = 'b', 'a', 'r', '\0', ...;,它们将会是。 @RSahu:即使您使用char foo[][4] = "bar", "foo", "", "baz",它们也会如此——不知道他为什么不这么认为。 当你没有为数组提供足够的初始化器时,剩余部分不是未定义的,它是零填充的。将字符串用作初始化程序时不会出现异常,是吗? @JonathanMee:等等,你的意思是当你创建两个具有相同值的字符串文字时,编译器会给它们相同的地址?它可能会,但这不是标准的保证。无论如何,根据我之前的评论,这是一个独立的问题。这只有在我们使用字符串字面量初始化指针时才有意义。【参考方案2】:

来自 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)维数组,它本身 如果用作左值以外的值,则转换为指针。 它 由此得出,数组以行优先顺序存储(最后 下标变化最快)。

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

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

【讨论】:

以上是关于子数组是不是保证线性分配? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

最大连续子数组,线性时间解法

创建线性二维数组的子数组

最大和子数组 O(n) 不是 Kadane 的

指向包含可分配数组的派生类型的指针

#yyds干货盘点# 解决剑指offer: 连续子数组的最大和

线性扫描算法求数组中的最大子序列