В a + 1
, a
ухудшается до указателя на его первый элемент (int*
), затем добавление одного получает указатель на a[1]
, потому что он настраивает указатель в соответствии с размером, на который он указывает (int
).
В &a + 1
, &a
получает указатель на все из a
;это int(*)[5]
(то есть указатель на массив из пяти int
s), начинающийся с того же адреса, что и a[0]
, и добавление 1
корректирует указатель в соответствии с размером того, на что он указывает (перемещая егонаряду с пятью int
с), что фактически указывает на a[5]
;затем он уменьшается до int*
, когда вы присваиваете ему p1
, который является int*
.
После этого вы вычитаете по одному из каждого, поэтому p - 1
возвращается на один int
и указываетдо a[0]
, тогда как p1 - 1
также возвращается на единицу int
, но с начальной точки a[5]
, поэтому она указывает на a[4]
.Таким образом, разыменование p - 1
возвращает вам первый элемент в массиве, а разыменование p1 - 1
- последний.