В языке C вы можете создать «пробку» из указателей, направленных на одну и ту же область памяти. Это не ошибка. Это особенность языка. Вы можете объявить столько указателей, сколько захотите, и все они будут ссылаться на одну и ту же переменную.

Рассмотрим такой сценарий. У вас есть целочисленная переменная i. Также у вас есть три указателя: p, q и r. Вы устанавливаете p так, чтобы он указывал на i. Затем вы устанавливаете q так, чтобы он указывал на i. Наконец, вы устанавливаете r так, чтобы он указывал туда же, куда указывает p.

В этом фрагменте кода r указывает на то же самое, что и p, а именно на i. Оператор присваивания копирует адрес из правой части в левую. Он не копирует значение, он копирует адрес.

После выполнения кода у переменной i появляется четыре имени. Сама i, *p, *q и *r.

Нет ограничений на количество указателей, которые могут хранить один и тот же адрес. Их можно цепочкой передавать друг другу, копировать или одновременно направлять на одну область.

Почему это важно? Это важно, потому что это меняет ваше представление о памяти. Указатель — это просто метка для адреса. Если несколько меток указывают на одно и то же место, они все видят одни и те же данные. Измените данные через *p*q тоже увидит эти изменения.

Эта гибкость мощна. Она также опасна. Одна опечатка в присваивании указателя, и вы перезапишете данные, которые не намеревались изменять. Но пока просто поймите, что указатели гибки. Они не владеют памятью, они лишь указывают на неё. И несколько указателей могут указывать на одно и то же место без конфликтов.