子数组是不是保证线性分配? [复制]
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 这绝对不是骗子,因为他malloc
s 内存在一个循环中,所以你绝对不能保证这些子数组在内存中的布局。
@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"
那你为什么说这是保证int
s 的呢?
@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/p20(Emphasis 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)
维数组,它本身 如果用作左值以外的值,则转换为指针。 它 由此得出,数组以行优先顺序存储(最后 下标变化最快)。
从上面我们可以得出结论,一个二维数组实际上是一个以行优先顺序存储的一维数组。
因此,可以安全地假设子数组的元素连续存储在内存中。
【讨论】:
以上是关于子数组是不是保证线性分配? [复制]的主要内容,如果未能解决你的问题,请参考以下文章