Во-первых, правильный способ печати указателей - с помощью %p
и с указателем, преобразованным в void *
при передаче в printf
, как в printf("%p\n", (void *) ptr);
. Поскольку вы упоминаете в комментарии, что использовали %P
, в отличие от %u
, показанного в вопросе, я предполагаю, что неверный случай является опечаткой, и вы воспроизвели проблему, используя %p
с результатами, аналогичными показанным в вопрос.
В этом случае вероятно то, что компилятор хранит указатели ptr
, pptr
, ppptr
и pppptr
по адресам, которые находятся на расстоянии 12 байтов друг от друга. Конечно, он мог бы хранить их всего в четырех или восьми байтах друг от друга, если бы указатели в вашей реализации C имели размер четыре или восемь байтов. Однако компилятор может хранить между указателями другие вещи, например адреса строк, которые вы используете в операторах printf
, или другие случайные значения. Это заставляет меня подозревать, что вы скомпилировали без включенной оптимизации. Если вы перекомпилируете с оптимизацией, вы, скорее всего, увидите другие результаты.
В любом случае, лучшее объяснение результатов можно было бы получить, попросив компилятор показать код сборки, который он генерирует (как при использовании переключателя -S
с GCC).