Эта строка неверна:
p = a[0];
Тип p
является указателем на массив 3 int
.Тип a[0]
является указателем на int
.Ваш компилятор должен был предупредить вас об этом.Если это не так, включите все необходимые параметры, чтобы включить большинство или все предупреждения вашего компилятора.Когда компилятор выдает предупреждение, не игнорируйте его - убедитесь, что вы понимаете, почему компилятор выдает предупреждение, прежде чем продолжить.Было бы неплохо включить функцию компилятора, которая превращает предупреждения в ошибки.
Правильный оператор будет p = a;
или p = &a[0];
.Но давайте рассмотрим, что произошло в вашей программе.В выражении a[0]
:
- По определению подстрочного оператора
a[0]
эквивалентно *(a+0)
(технически (*((a)+(0)))
, но в этом случае нам не нужны дополнительные скобки). a
- это массив, поэтому он преобразуется в указатель на свой первый элемент.Таким образом, a
преобразуется в указатель на a[0]
.Таким образом, выражение теперь *(&a[0] + 0)
. - Добавление
0
к &a[0]
не меняет его, поэтому результат равен &a[0]
, а выражение теперь *&a[0]
. a[0]
- это массив из 3 int
.Поскольку это массив, он преобразуется в указатель на свой первый элемент.Таким образом, результат фактически равен &a[0][0]
.
Обратите внимание, что &a[0][0]
является указателем на int
, как я писал выше.Итак, теперь мы видим, что p = a[0];
имеет указатель на int
справа, но указатель на массив 3 int
слева.Это нарушает ограничение в стандарте C, и компилятор должен выдать ему диагностическое сообщение.
После предупреждения ваш компилятор, вероятно, сделал преобразование указателя, в результате чего p
устанавливается в значение a[0]
.
Я преобразовал 2-ю инструкцию p=a[0]
в p=&a[0][0]
(, потому что a[0]
- это имя подмассива, чей 1-й элемент - a[0][0]
).Так что (*p)
можно записать как (*(&a[0][0]))
.
Это ошибка.Хотя вы выполнили присваивание p = a[0]
, это не присвоило &a[0][0]
p
, и p
не ведет себя так, как если бы оно было &a[0][0]
.Назначение преобразуется &a[0][0]
в тип p
.p
остается типом, который был объявлен, указателем на массив 3 int
.По сути, p
заканчивается значением &a[0]
.
Теперь мы можем оценить (*p)[i]
:
p
равно &a[0]
, поэтому выражениестановится (*&a[0])[i])
. *&a[0]
равно a[0]
, поэтому выражение становится a[0][i]
. - Оттуда мы можем приступить к обычной оценке выражения, и ясно, чторезультат - элемент
i
элемента 0 из a
.