C позволяет создать «толпу» вокруг одной ячейки памяти. Вам не нужно ограничиваться одним указателем. Любое количество указателей может указывать на один и тот же адрес. Это не ошибка. Это особенность того, как C обрабатывает ссылки на память.
Рассмотрим простую переменную целого типа i. Вы можете объявить три различных указателя: p, q и r. Код предельно прост.
Посмотрите на последнюю строку. r указывает на то же самое, на что указывает p. А поскольку p уже присвоен адрес i, r фактически тоже указывает на i.
Оператор присваивания копирует адрес из правой части в левую. Он не копирует значение, хранящееся по этому адресу. Он копирует сам адрес. Это ключевое различие в арифметике указателей.
После выполнения кода у i появляется четыре имени. Вы можете обращаться к целому числу как к i. Вы можете изменять его через *p. Вы можете читать его через *q. Вы также можете обращаться к нему с помощью *r.
Нет предела тому, сколько указателей могут хранить один и тот же адрес. Вы можете объявить s, t и u, если хотите. Все они будут просто псевдонимами для одного и того же участка памяти.
Эта гибкость имеет значение. Она позволяет функциям делиться ссылками на данные без копирования больших структур. Она позволяет создавать сложные структуры данных, где несколько узлов указывают на одного и того же потомка. Она делает управление ресурсами в C более эффективным.
Но это также вносит риск. Если один указатель изменяет значение, все указатели видят это изменение. Нет изоляции. Нужно быть осторожным. Один указатель изменяет целое число. Другие видят это немедленно.
Переменная
iтеперь имеет четыре имени:i,*p,*qи*r.
Это базовая арифметика указателей. Она фундаментальна для понимания моделей памяти в C. Но именно здесь начинаются трудности. Несколько ссылок на один адрес означают несколько способов испортить данные.
Вы можете бесконечно цепочить присваивания указателей. s = r; t = s;. Всё это указывает обратно на i. Компилятору всё равно. Время выполнения тоже всё равно. Это просто адреса памяти.
Почему это важно для обычных пользователей? Если вы пишете код на C, вы полагаетесь на это. Если вы отлаживаете падение программы, это часто является причиной. Ошибки использования после освобождения (use-after-free) процветают в средах, где указатели переназначаются, но не обнуляются.
Эффективность достигается ценой сложности. Вам нужно отслеживать, кто владеет данными. Кто имеет право их изменять. При наличии нескольких указателей такой контроль становится сложнее.
Но мощь этого механизма неоспорима. Вы можете передавать указатели в функции. Изменять значение. Исходная переменная отразит это изменение. Именно так C достигает семантики ссылок без использования объектов.
Это простая концепция. Копируйте адрес. Не копируйте значение. Позвольте нескольким именам ссылаться на одно место. Используйте это мудро.





























