Давайте начнем с некоторой справочной информации.
Сначала выражение ++i
оценивается в текущее значение i
плюс 1 - как побочный эффект , значение, сохраненное в i
, увеличивается на единицу. Как автономное выражение, оно примерно эквивалентно i = i + 1
.
Во-вторых, за исключением случаев, когда это операнд операторов sizeof
или унарных &
, выражение типа "массив N-элементов T
" (T [N]
) будет преобразуется («распад») в выражение типа «указатель на T
» (T *
), а значением выражения будет адрес первого элемента массива.
Наконец, выражение a[i]
является , определенным как *(a + i)
- с учетом начального адреса a
, смещение i
элементов (не байтов!) От этого адреса и разыменовывать результат. Это означает, что выражение a + i
эквивалентно выражению &a[i]
.
Посмотрим, как это относится к вашему коду:
В функции increment
строка
++ *ptr;
добавляет 1 к вещи, на которую указывает ptr
.
Когда вы вызываете increment(a)
, выражение a
имеет тип "массив из 2 элементов int
". Поскольку a
не является операндом операторов sizeof
или унарных &
, это выражение «затухает», чтобы ввести «указатель на int
» (int *
), а значение выражения является адресом первый элемент a
. Точно так же, как если бы вы написали increment(&a[0])
. Следовательно, в функции increment
выполняются следующие условия:
ptr == &a[0]
*ptr == a[0]
Таким образом, выражение ++ *ptr
эквивалентно выражению ++ a[0]
. После этого звонка a[0]
теперь 6.
Когда вы звоните increment(&i)
, ptr
теперь указывает на i
:
ptr == &i
*ptr == i
поэтому ++ *ptr
эквивалентно выражению ++ i
, поэтому вы добавляете 1 к i
.
Когда вы звоните increment(a[i])
, i
равен 1, так что это эквивалентно вызову increment(a[1])
. После этого вызова a[1]
равно 11.
И, наконец, increment(a+i)
эквивалентно increment(&a[i])
, что эквивалентно increment(&a[1])
, а после этого вызова a[1]
равно 12.