Reputation: 118
It seems the regular definition of the indirection operator doesn't apply when it is used on multi-dimensional arrays:
int arr[10][10][10];
If you dereference arr, you'll get the same address:
(void*)arr == (void*)*arr && (void*)*arr == (void*)**arr
This makes sense though - a multi-dimensional array is just a contiguous region of memory, where the pointer points at the beginning of the memory. The compiler essentially ignores dereferences and just computes the proper offset. Use of the indirection operator seems to only preserve the abstraction of multi-dimensional arrays and make it fit with the other syntactic constructs of the language.
If you do the following:
int *** ptr = (int***) arr;
And dereference ptr, you'll see the normal dereference behavior, where the value in the location specified by the pointer is returned. Using the above cast, you'll read into undefined memory if you dereference the pointer more than twice.
I'm just wondering why this behavior isn't documented in more places - that is, the difference of effect of the indirection operator on pointers to arrays vs pointers to pointers and pointers to values?
Upvotes: 1
Views: 1266
Reputation: 239331
Firstly, to fully understand this you must appreciate that C does not have multidimensional arrays - it has arrays of arrays. So, in your example, arr
is "an array of 10 arrays of 10 arrays of 10 ints".
Secondly, it's not the indirection operator that behaves differently, it's the behaviour of expressions with array type that's odd.
If an expression with array type is not the subject of either the unary &
or sizeof
operators1, then it evaluates to a pointer to the first element of that array.
This means that in the following expression:
(void*)*arr == (void*)**arr
On the left hand side, arr
evaluates to a pointer to the first array of 10 arrays of 10 ints within arr
(that is, &arr[0]
). This is then dereferenced to obtain that array itself: the first sub-array within arr, arr[0]
. However, since arr[0]
is itself an array, this then is replaced with a pointer to it's first element, &arr[0][0]
.
On the right hand side, the above happens as per the left hand side, then that last pointer is dereferenced, obtaining arr[0][0]
. This, again, is an array, so it is finally replaced with a pointer to its first element, &arr[0][0][0]
.
The reason these are equal (after conversion to void *
) is simply because the address of the array arr[0][0]
and the address of the int arr[0][0][0]
coincide, as the latter is the first member of the former. They also concide with the address of arr[0]
and arr
, so you also have:
(void *)&arr == (void *)arr;
(void *)arr == (void *)*arr;
as well.
Upvotes: 1