如果我按照以下方式浏览2D数组的元素,是不确定的行为?
int v[5][5], i;
for (i = 0; i < 5*5; ++i) {
v[i] = i;
}
然后,它甚至编译? (我现在不能尝试,我不在家。)如果没有,那么想象我以某种方式获得了指向第一个元素并使用taht而不是v[i]
的指针。
答案 0 :(得分:7)
从指向第一个元素的指针访问多维数组的元素是UB,表示不属于第一个数组的元素。
给定T array[n]
,array[i]
是所有i> = n的UB-land直行。即使T
是U[m]
。即使是通过指针。确实存在对数组的强烈要求(例如sizeof(int[N]) == N*sizeof(int)
),正如其他人所提到的那样,但没有明确的例外情况,因此无法对此做任何事情。
我没有正式的参考资料,因为据我所知,C ++标准将详细信息留给了C89标准,而且我不熟悉C89或C99标准。相反,我引用了comp.lang.c FAQ:
[...]根据官方解释,访问(&amp; array [0] [0])[x]的行为未定义为x&gt; = NCOLUMNS。
答案 1 :(得分:4)
它不会编译。
更少的等价物
int v[5][5], *vv, i;
vv = &v[0][0];
for (i = 0; i < 5*5; ++i) {
vv[i] = i;
}
和
int v[5][5], i;
for (i = 0; i < 5*5; ++i) {
v[0][i] = i;
}
将编译。我不确定它们是否是UB(事实上它在C90,C99和C ++之间可能有所不同;混叠是一个棘手的领域)。我会尝试以某种方式找到参考文献。
答案 2 :(得分:2)
这里v[i]
代表5个元素的整数数组。
一个整数数组由一个地址位置引用,这取决于你的'c'编译器可能是16位,32位......
所以v[i] = i
可以在一些编译器中编译....但它肯定不会产生你正在寻找的结果。
sharptooth的回答是正确的v[i][j] = i
...是最简单易读的解决方案之一..
其他可能是
int *ptr;
ptr = v;
现在你可以迭代这个ptr来分配值
for (i = 0; i < 5*5; i++, ptr++) {
*ptr = i;
}
答案 3 :(得分:1)
很难在标准中找到任何引用明确指出这是未定义的行为。当然,标准明确指出(C996.5.6§8-9),如果你在数组之外做指针算术,那就是UB。那么问题是,数组的定义是什么?
如果多维数组被视为数组对象的数组,那么它就是UB。但如果它被视为具有多个维度的一个数组,则代码将完全正常。
标准附件J中另一个未定义的行为有一个有趣的注释:
数组下标超出范围, 即使一个物体显然也是如此 可以使用给定的下标访问 (如左值表达式a [1] [7] 在[4] [5]中给出声明 (6.5.6)。
这个暗示访问第一维范围之外的多维数组是未定义的行为。但是,附件不是规范性文本,6.5.6是相当低的。
也许有人可以找到数组对象和多维数组之间差异的明确定义?在那之前,我不相信这是UB。
编辑:忘记提及v [i]肯定不是有效的C语法。根据6.5.2.1,v [i]等价于*(v + i),它是一个数组指针而不是数组元素。我不确定的是,v[0][too_large_value]
访问它是否是UB。
答案 4 :(得分:0)
这不会编译。
您将收到该行的以下错误:
v[i] = i;
错误:将'int'赋值给'int [5]'
的类型不兼容在以下方面提出类似问题的答案:
http://www.velocityreviews.com/forums/t318379-incompatible-types-in-assignment.html
v是2D数组。由于您只引用了一个维度,最终得到的是指向底层数组的char指针,因此该语句试图将char常量赋给char指针。 您可以使用双引号将常量更改为C样式的字符串,也可以显式引用v [i] [0],这是我假设您的意图。