Выражение *ptr++
анализируется как *(ptr++)
и оценивается следующим образом:
- Получить текущее значение
ptr
- Разыменование этого значения указателя для получения целочисленного значения
- В какой-то момент перед следующей точкой последовательности добавьте 1
sizeof *ptr
к ptr
.
Это примерно эквивалентно написанию
x = *ptr;
ptr = ptr + sizeof *ptr;
за исключением того, что побочный эффект обновления ptr
может произойти в любое время до следующей точки последовательности ( никогда предполагает, что побочные эффекты применяются в определенном порядке); IOW, последовательность может быть
tmp = ptr;
ptr = ptr + sizeof *ptr;
x = *tmp;
В этом случае точка последовательности находится в конце вызова функции printf
.
Выражение *(++ptr)
анализируется как записанное и оценивается следующим образом:
- Получить текущее значение
ptr + sizeof *ptr
- Отмените значение этого указателя для получения целочисленного значения
- В какой-то момент перед следующей точкой последовательности добавьте 1
sizeof *ptr
к ptr
что примерно эквивалентно написанию
tmp = ptr + sizeof *ptr;
x = *tmp;
ptr = ptr + sizeof *ptr;
, где, опять же, побочный эффект обновления значения ptr
может произойти в любой точке до следующей точки последовательности; IOW, последовательность может быть
tmp = ptr + sizeof *ptr;
ptr = ptr + sizeof *ptr;
x = *tmp;
Вот гипотетическая карта памяти при запуске программы (предположим, 32-битные адреса и 16-битные значения):
Item Address 0x00 0x01 0x02 0x03
---- -------- ---- ---- ---- ----
my_array 0x08000000 0x00 0x01 0x00 0x17
0x08000004 0x00 0x11 0x00 0x04
0x08000008 0xff 0xfb 0x00 0x64
ptr 0x0800000C 0x00 0x00 0x00 0x00
i 0x10008000 0x?? 0x?? 0x?? 0x??
0x??
указывает случайное значение байта. Поскольку ptr
объявлено в области видимости файла, оно имеет статический экстент и неявно инициализируется значением NULL. Поскольку i
объявлен auto
, он не инициализирован и содержит случайный мусор.
После выполнения оператора ptr = &my_array[0]
значение ptr
равно 0x08000000
.
При выполнении строки
printf("ptr + %d = %d", i, *ptr++);
выражение *ptr++
разыменовывает память по адресу 0x08000000
, который содержит значение 1, поэтому на выходе получается
ptr + 0 = 1
Побочный эффект оператора ++
обновляет значение с ptr
до 0x08000002
.
При выполнении строки
printf("ptr + %d = %d, i, *(++ptr));
выражение *(++ptr)
задерживает память на 0x08000004
, а не 0x08000002
, поскольку выражение ++ptr
оценивается как ptr + sizeof *ptr
. Таким образом, вывод этой строки
ptr + 0 = 17
и побочный эффект оператора ++
обновляет значение с ptr
до 0x08000004
.
Таким образом, когда вы зацикливаетесь, ваш вывод будет выглядеть как
my_array[0] = 1 /* ptr = 0x08000000 */
ptr + 0 = 1
ptr + 0 = 1 /* ptr = 0x08000002 after */
ptr + 0 = 17 /* ptr = 0x08000004 after */
my_array[1] = 23
ptr + 1 = 4
ptr + 1 = 4 /* ptr = 0x08000006 after */
ptr + 1 = -5 /* ptr = 0x08000008 after */