If we "draw" the array arr on paper it will look like this
+-----------+-----------+-----------+-----------+-----------+-----+
| arr[0][0] | arr[0][1] | arr[0][2] | arr[0][3] | arr[1][0] | ... |
+-----------+-----------+-----------+-----------+-----------+-----+
From this it should be easy to see that pointers to the array, the first element of the array, and the first sub-element of the first element will all be the same.
That is, &arr == &arr[0] and &arr[0] == &arr[0][0] (which of course means that &arr == &arr[0][0]).
The differences here is the types:
- &arris of the type- int (*)[3][4]
- &arr[0]is of the type- int (*)[4]
- And &arr[0][0]is of the typeint *
Now as for arr and *arr, you have to remember that arrays naturally decays to pointers to their first elements. This means arr will be equal to &arr[0]. And dereferencing a pointer will be the "value" being pointed to, so *arr is equal to *(&arr[0]) which is then equal to arr[0] which in turn will decay to &arr[0][0].