Одномерный доступ к многомерному массиву: хорошо ли определено поведение?
Я полагаю, что мы все согласны с тем, что считается идиоматическим C для доступа к истинному многомерному массиву путем разыменования (возможно смещенного) указателя на его первый элемент одномерным способом, например :
void clearBottomRightElement(int *array, int M, int N)
{
array[M*N-1] = 0; // Pretend the array is one-dimensional
}
int mtx[5][3];
...
clearBottomRightElement(&mtx[0][0], 5, 3);
Однако, языковой адвокат во мне нуждается в убеждении, что это на самом деле четко определенный C! Особенно
Имеет ли стандартную гарантию, что компилятор не будет вставлять промежуточные отступы, напримерmtx[0][2]
а такжеmtx[1][0]
?
Нормально, индексирование конца массива (кроме одного после конца) не определено (C99, 6.5.6 / 8). Таким образом, следующее явно не определено:
struct {
int row[3]; // The object in question is an int[3]
int other[10];
} foo;
int *p = &foo.row[7]; // ERROR: A crude attempt to get &foo.other[4];
По тому же правилу можно ожидать, что следующее будет неопределенным:
int mtx[5][3];
int (*row)[3] = &mtx[0]; // The object in question is still an int[3]
int *p = &(*row)[7]; // Why is this any better?
Так почему это должно быть определено?
int mtx[5][3];
int *p = &(&mtx[0][0])[7];
Так какая часть стандарта C явно разрешает это? (Давайте предположим, что C99 ради обсуждения.)
РЕДАКТИРОВАТ
Обратите внимание, что я не сомневаюсь, что это прекрасно работает во всех компиляторах. Я спрашиваю, разрешено ли это стандартом.