Давайте проигнорируем неопределенное поведение, чтобы выяснить, что, вероятно, происходит.
p1
и p2
оба указывают на a[0]
(игнорируя несовместимые типы указателей).
p1
и p2
оба указатели. Указатели на типы объектов обычно имеют одинаковый размер (предположим, что это так), поэтому sizeof(p1)==sizeof(p2)
будет истинным.
p1
имеет тип int (*)[2]
, поэтому *p1
имеет тип int[2]
. В большинстве выражений массив будет уменьшаться до указателя на его первый элемент, поэтому в выражении *(*p1+2)
, *p1
будет уменьшаться до int *
и будет указывать на a[0]
. Следовательно, *p1+2
будет указывать на a[2]
. Поэтому *(*p1+2)
будет таким же, как a[2]
, который имеет значение 30
. Поэтому программа печатает 30
.
Массив не затухает до указателя, когда он является операндом оператора sizeof
. *p1
имеет тип int[2]
и *p2
имеет тип int[3]
, поэтому sizeof(*p1)==sizeof(*p2)
эквивалентно sizeof(int[2])==sizeof(int[3])
, что неверно. Поэтому второй вызов printf
, который печатает значение *(*p2+1)
, не оценивается.
(Давайте представим, что вызывается второй printf
и вычисляется *(*p2+1)
. *p2
имеет тип int[3]
и в этом выражении оно уменьшается до int *
, указывающего на a[0]
. Поэтому *p2+1
указывает на a[1]
. Следовательно, *(*p2+1)
будет таким же, как a[1],
, который имеет значение 20
. )