Это неопределенное поведение, и вот почему.
Доступ к многомерному массиву можно разбить на серию обращений к одномерному массиву. Другими словами, выражение 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).
person
Drew McGowen
schedule
05.08.2014