二维数组索引 - 不确定的行为?

二维数组索引 - 不确定的行为?

问题描述:

我最近陷入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 that E1[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).