二维数组索引 - 不确定的行为?
我最近陷入code的一些作品做了一些可疑的二维数组索引操作。考虑到作为一个例子下面code样品:
I've recently got into some pieces of code doing some questionable 2D arrays indexing operations. Considering as an example the following code sample:
int a[5][5];
a[0][20] = 3;
a[-2][15] = 4;
a[5][-3] = 5;
在上面受到不确定的行为索引操作?
Are the indexing operations above subject to undefined behavior?
这是未定义的行为,这里的原因。
It's undefined behavior, and here's why.
多维数组访问可以被分解成一系列的单维阵列的访问。换句话说,前pression A [I] [J]
可以被认为是(A [])[J]。
。引用C11§6.5.2.1/ 2:
Multidimensional array access can be broken down into a series of single-dimensional array accesses. In other words, the expression a[i][j]
can be thought of as (a[i])[j]
. Quoting C11 §6.5.2.1/2:
下标运算符 []
的定义是: E1 [E2]
与(*((E1)+(E2)))
。
The definition of the subscript operator
[]
is thatE1[E2]
is identical to(*((E1)+(E2)))
.
这意味着上述等同于 *(*(A + I)+ J)
。继C11§6.5.6/ 8对另外一个整数和指针(重点煤矿)的:
This means the above is identical to *(*(a + i) + j)
. Following C11 §6.5.6/8 regarding addition of an integer and pointer (emphasis mine):
如果这两个指针
操作数和结果指向相同的数组对象的元素,或者一个过去的最后
数组对象的元素,该评估也不得产生溢出;的否则,
行为是未定义的
在换句话说,如果 A [I]
不是一个有效的指数,该行为是立即不确定的,即使直觉 A [ I] [J]
似乎是在界外。
In other words, if a[i]
is not a valid index, the behavior is immediately undefined, even if "intuitively" a[i][j]
seems in-bounds.
所以,在第一种情况下, A [0]
是有效的,但下面的 [20]
是不会,因为的类型[0]
是 INT [5]
。因此,指数20就是出界。
So, in the first case, a[0]
is valid, but the following [20]
is not, because the type of a[0]
is int[5]
. Therefore, index 20 is out of bounds.
在第二种情况下, A [-1]
已经超出边界,从而已经UB。
In the second case, a[-1]
is already out-of-bounds, thus already UB.
在过去的情况下,然而,前pression A [5]
指向一个过去的数组,这是因为每§有效的最后一个元素6.5.6 / 8:
In the last case, however, the expression a[5]
points to one past the last element of the array, which is valid as per §6.5.6/8:
...如果EX pression P
指向数组对象的最后一个元素,前pression ( p)+1
点中的一个过去的数组对象...
... 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)。
So, while a[5]
is a valid pointer, dereferencing it will cause undefined behavior, which is caused by the final [-3]
indexing (which, is also out-of-bounds, therefore UB).