Все массивы (включая многомерные) не содержат отступов. Даже если это никогда явно не упоминается, оно может быть выведено из sizeof
правил.
Теперь подписка на массив является частным случаем арифметики указателей, и в разделе 6.5.6, §8 раздела C99 четко указано, что поведение определяется только в том случае, если операнд указателя и результирующий указатель лежат в одном и том же массиве (или один элемент после) , что делает возможной реализацию проверок границ языка Си.
Это означает, что ваш пример - фактически неопределенное поведение. Однако, поскольку большинство реализаций C не проверяют границы, оно будет работать как положено - большинство компиляторов обрабатывают неопределенные выражения указателя, такие как
mtx[0] + 5
идентично четко определенным аналогам, таким как
(int *)((char *)mtx + 5 * sizeof (int))
, который четко определен, потому что любой объект (включая весь двумерный массив) всегда может рассматриваться как одномерный массив типа char
.
О дальнейшей медитации над формулировкой раздела 6.5.6, разделив доступ за пределы границ на, казалось бы, четко выраженное подвыражение, подобное
(mtx[0] + 3) + 2
обоснование того, что mtx[0] + 3
является указателем на один элемент после конца mtx[0]
(что делает первое добавление четким), а также указателем на первый элемент mtx[1]
(что делает второе добавление правильным -определено) неверно:
Даже если mtx[0] + 3
и mtx[1] + 0
гарантированно сравниваются равными (см. Раздел 6.5.9, §6), они семантически различны. Например, первое не может быть разыменовано и поэтому не указывает на элемент mtx[1]
.