A 2D array is an array of arrays. a 3D array is an array of arrays of arrays. in this case we have an array of 2 arrays each of which is of 3 arrays each of which is 2 elements long.
recall that, in C, when an array name used by itself in a place of a pointer, it decays to a pointer to the first element in that array. another thing is that the address of an array is the same address as the address of the first element in that array.
by that, all of the following pointers point to the same location (though they mean different things):
a
- a pointer to the first element in the 3D-array a
(&a[0]
).
&a
- a pointer to the whole 3D-array a
.
a[0]
- a pointer to the first element in the 2D-array a[0]
(&a[0][0]
).
&a[0]
- a pointer to the whole 2D-array a[0]
a[0][0]
- a pointer to the first element in the array a[0][0]
(&a[0][0][0]
)
&a[0][0]
- a pointer to the whole array a[0][0]
similarly, the following point to the same location (though mean different things)
a[1]
- points to the first element in the 2D-array a[1]
(&a[1][0]
)
&a[1]
- points to the whole 2D-array a[1]
a[1][0]
- points to the first element in the array a[1][0]
(&a[1][0][0]
)
we also know that array elements live in contiguous locations in memory. given the next piece of code:
int arr[] = {1, 2};
int* p0 = &arr[0]; // points to the first element
int* p1 = &arr[1]; // points to the second element
printf("%u\n", p1 - p0); // outputs 1 (not 4)
although p1
is 4 bytes after p0
(because an int
is 4 bytes long on the appliance), the result of subtracting p0
from p1
gives 1
not 4
— meaning 1 unit of the size of the type of values pointed to by these pointers (here the pointers point to int
s, so a unit is 4 bytes long).
between a[0]
and a[1]
there are 6 elements (a total of 24 bytes). that means that if a[0]
points to location 100
, a[1]
should be pointing to location 124
. but wait!! didn't a[1] - a[0]
just give us 3
?
well, yes, and the reason is that each of a[0]
and a[1]
are the same as &a[0][0]
and &a[1][0]
respectively. both a[0][0]
and a[1][0]
are 2-element int
arrays (int[2]
). following the logic above, the size of int[2]
is 2 int
s × 4 bytes = 8 bytes.
the expression above evaluated to 3
because 3
units × 8 bytes = 24 bytes.
similarly, a[0][0]
and a[1][0]
are the same as &a[0][0][0]
and &a[1][0][0]
. the different, in bytes, is still 24. however, the type of a[0][0][0]
and a[1][0][0]
is just int
, so the size of a unit is 4 and that explains why a[1][0] - a[0][0]
gives 6
(6 units × 4 bytes = 24 bytes).
the last expression, a[1][0][0] - a[0][0][0]
doesn't involve pointer arithmetic and is fairly obvious!