dra*_*sht 4 c arrays multidimensional-array undefined-behavior
我最近进入了一些代码,做了一些有问题的2D数组索引操作.以下面的代码示例为例:
int a[5][5];
a[0][20] = 3;
a[-2][15] = 4;
a[5][-3] = 5;
Run Code Online (Sandbox Code Playgroud)
上面的索引操作是否受到未定义的行为的影响?
这是未定义的行为,这就是原因.
多维数组访问可以分解为一系列单维数组访问.换句话说,表达式a[i][j]可以被认为是(a[i])[j].引用C11§6.5.2.1/ 2:
下标操作符的定义
[]是E1[E2]相同(*((E1)+(E2))).
这意味着以上内容完全相同*(*(a + i) + j).在C11§6.5.6/ 8之后关于添加整数和指针(强调我的):
如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; 否则,行为未定义.
换句话说,如果a[i]不是有效索引,则行为立即未定义,即使"直观" a[i][j]似乎是入境的.
所以,在第一种情况下,a[0]是有效的,但以下[20]不是,因为类型a[0]是int[5].因此,索引20超出范围.
在第二种情况下,a[-1]已经超出界限,因此已经是UB.
但是,在最后一种情况下,表达式a[5]指向一个超过数组最后一个元素的表达式,根据§6.5.6/ 8有效:
...如果表达式
P指向数组对象的最后一个元素,则表达式(P)+1指向数组对象的最后一个元素之后的一个...
但是,在同一段后面:
如果结果指向数组对象的最后一个元素之后,则不应将其用作已计算的一元*运算符的操作数.
因此,虽然a[5]是一个有效的指针,但是解引用它会导致未定义的行为,这是由最终[-3]索引引起的(其也是越界,因此是UB).