Acesso unidimensional a uma matriz multidimensional: é um comportamento bem definid
Imagino que todos concordamos que é considerado C idiomático acessar uma matriz multidimensional verdadeira desreferenciando um ponteiro (possivelmente compensado) para seu primeiro elemento de uma maneira unidimensional, por exemplo :
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);
No entanto, o advogado de idiomas em mim precisa convencer que isso é C bem definido! Em particular
Garantia padrão de que o compilador não colocará preenchimento no meio, por exemplomtx[0][2]
emtx[1][0]
?
Normalmente, a indexação do final de uma matriz (que não seja um final após o final) é indefinida (C99, 6.5.6 / 8). Portanto, o seguinte é claramente indefinido:
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];
Portanto, pela mesma regra, seria de esperar que o seguinte seja indefinido:
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?
Então, por que isso deve ser definido?
int mtx[5][3];
int *p = &(&mtx[0][0])[7];
Então, que parte do padrão C permite explicitamente isso? (Vamos assumir c99 por uma questão de discussão.)
EDITA
Note que não tenho dúvidas de que isso funciona bem em todos os compiladores. O que estou perguntando é se isso é explicitamente permitido pelo padrão.