Помните, что когда выражение типа "массив N-элементов из T
" появляется в большинстве контекстов, оно будет преобразовано в выражение типа "указатель на T
", а его значением будет адреспервый элемент в массиве.Исключениями из этого правила являются случаи, когда выражение массива является операндом либо sizeof
, либо унарным &
(address-of) операндами, либо если выражение массива является строковым литералом, используемым в качестве инициализатора в объявлении массива.
Ваша ситуация является зеркальным отображением следующего:
int a[10] = {0};
printf("a = %p, &a = %p\n", (void *) a, (void *) &a);
В вызове printf
выражение a
имеет свой тип, преобразованный из "массива из 10 элементов int
"to" указатель на int
"на основе приведенного выше правила, и его значением будет адрес первого элемента (&a[0]
).Выражение &a
имеет тип «указатель на массив из 10 элементов int
», и его значение будет таким же, как a
(адрес первого элемента в массиве совпадает с адресом массивасам).
Ваш код имеет немного неопределенное поведение, так как вы разыменовываете r
до того, как он был назначен для указания где-либо значимого, так что вы не можете поверить, что выходные данные вообще точны.Мы можем исправить это так:
int a[10] = {0};
int (*r)[10] = &a;
printf("r = %p, *r = %p\n", (void *) r, (void *) *r);
В этом случае r == &a
и *r == a
.
Выражение r
имеет тип "указатель на массив из 10 элементов с int
", а его значением является адрес a
.Выражение *r
имеет тип "массив из 10 элементов int
, который преобразуется в" указатель на int
", а его значение устанавливается на адрес первого элемента, который в данном случае равен a[0]
Опять же, значения двух выражений одинаковы.