In memory, the array char a[4] = {1, 2, 3, 4}
looks likes this:
[(1)(2)(3)(4)]
with ()
representing a byte of memory and []
hinting you where the array begins/ends.
The array char a[2][2] = {{1, 2}, {3, 4}}
looks like this in memory:
[[(1)(2)][(3)(4)]]
See, there is no difference, as []
don't really exist in memory, they are just hints I used in my reply. Effectively, if you don't know anything about the arrays and just look at the content of the raw bytes in memory, you'll see:
(1)(2)(3)(4)
in both cases.
Thus instead of creating an array a[Xmax][Ymax]
and accessing the elements using a[x][y]
, you can as well create the array as b[Xmax * Ymax]
and access the elements using b[x * Xmax + y]
, as that's in fact what happens behind the scenes anyway.
And in C, you can always turn an array reference into a pointer, as an array reference is a reference to a memory location where an array is located and a pointer is a reference to a memory location (regardless if an array is located there or not). So
int a[5] = { ... };
int * b = a;
works as a
is a reference to an int array, which are just several int values stored in memory, and b
is a pointer to a memory location where an int value is stored. Well, at the address where the array a
starts, an int value is stored, so this assignment is perfectly correct.
And m[3]
just means "increase the memory address m
references three times by the size of the value type m
references and fetch the value from that address". And that works and returns the expected value, no matter if m
is a pointer or an array reference. So while this syntax is actually intended for array access, it also works with pointers.
The syntax for a pointer would actually be *(m + 3)
, which means "increase the pointer address three times by the size of the value type it points to and then fetch the value from that address". Yet, just in the first case, this syntax would work with an array reference as well, since an array reference can always become a pointer when required.