Во-первых, чтобы полностью понять это, вы должны понимать, что C не имеет многомерных массивов - у него есть массивы массивов. Итак, в вашем примере arr
- это "массив из 10 массивов из 10 массивов по 10 дюймов" .
Во-вторых, по-другому ведет себя не оператор косвенного обращения, а странное поведение выражений с типом массива.
Если выражение с типом массива является , а не субъектом унарных &
или sizeof
операторов 1 , то оно оценивается как указатель на первый элемент этот массив.
Это означает, что в следующем выражении:
(void*)*arr == (void*)**arr
С левой стороны, arr
вычисляет указатель на первый массив из 10 массивов по 10 дюймов в пределах arr
(то есть &arr[0]
). Затем разыменовывается для получения самого этого массива: первого подмассива в arr, arr[0]
. Однако, поскольку arr[0]
сам по себе является массивом, он заменяется указателем на это первый элемент, &arr[0][0]
.
С правой стороны, вышеупомянутое происходит с левой стороны, затем разыменовывается последний указатель, получая arr[0][0]
. Это опять-таки массив, поэтому он наконец заменяется указателем на свой первый элемент, &arr[0][0][0]
.
Причина, по которой они равны (после преобразования в void *
), заключается просто в том, что адрес массива arr[0][0]
и адрес int arr[0][0][0]
совпадают, так как последний является первым членом первого. Они также соответствуют адресам arr[0]
и arr
, поэтому у вас также есть:
(void *)&arr == (void *)arr;
(void *)arr == (void *)*arr;
.
1. ..и не строковый литерал, используемый в инициализаторе.