我最近研究了一些代码来执行一些有问题的二维数组索引操作。以下面的代码示例为例:
int a[5][5];
a[0][20] = 3;
a[-2][15] = 4;
a[5][-3] = 5;
上述索引操作是否受制于未定义的行为?
最佳答案
这是未定义的行为,原因如下。
多维数组访问可以分解为一系列的一维数组访问。换句话说,表达式 a[i][j]
可以认为是 (a[i])[j]
.引用 C11 §6.5.2.1/2:
The definition of the subscript operator
[]
is thatE1[E2]
is identical to(*((E1)+(E2)))
.
这意味着以上内容与 *(*(a + i) + j)
相同.按照 C11 §6.5.6/8 关于整数和指针的加法(强调我的):
If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
换句话说,如果a[i]
不是有效索引,行为立即未定义,即使“直观地”a[i][j]
似乎在界内。
所以,在第一种情况下,a[0]
有效,但以下 [20]
不是,因为 a[0]
的类型是int[5]
.因此,索引 20 超出范围。
在第二种情况下,a[-1]
已经出界,因此已经是 UB。
然而,在最后一种情况下,表达式 a[5]
指向数组最后一个元素之后的一个,根据 §6.5.6/8 有效:
... if the expression
P
points to the last element of an array object, the expression(P)+1
points one past the last element of the array object ...
但是,在同一段的后面:
If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated.
所以,虽然 a[5]
是一个有效的指针,取消引用它会导致未定义的行为,这是由最终 [-3]
引起的索引(这也是越界的,因此是 UB)。
关于c - 二维数组索引 - 未定义的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25139579/