I imagine we all agree that it is considered idiomatic C to access a true multidimensional array by dereferencing a (possibly offset) pointer to its first element in a one-dimensional fashion, e.g.:
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);
However, the language-lawyer in me needs convincing that this is actually well-defined C! In particular:
Does the standard guarantee that the compiler won't put padding in-between e.g.
mtx[0][2]
andmtx[1][0]
?Normally, indexing off the end of an array (other than one-past the end) is undefined (C99, 6.5.6/8). So the following is clearly undefined:
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];
So by the same rule, one would expect the following to be undefined:
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?
So why should this be defined?
int mtx[5][3]; int *p = &(&mtx[0][0])[7];
So what part of the C standard explicitly permits this? (Let's assume c99 for the sake of discussion.)
EDIT
Note that I have no doubt that this works fine in all compilers. What I'm querying is whether this is explicitly permitted by the standard.
[][]
access is the same as*(array + x * index + y)
. – Janinejanisarr + 1 * 5 * sizeof(arrType) + 5 * sizeof (arrType)
... – Shortenmtx
is actually anint[5][3]
, but it decays to anint(*)[3]
. – Debugint *p = (int*)&mtx;
? – Holmgren