Указатели, ссылки, адреса
В предыдущий раз мы поговорили организации памяти в вычислителе, теперь поговорим как обращаться к этой памяти напрямую.
Важно отметить, что из-за принципов работы с указателями и ссылками (их арифметики) вы можете вылезти за пределы своей программы и работать с некорректными данными, или помешать другой программе.
необходимо отслеживать границы (особенно актуально для массивов)
Взятие адреса (С/С++)
У памяти есть адресация, следовательно можно получить адрес переменной в памяти, для этого используется амперсанд & (EN shift+7)
int Value=15; //переменная, хранящаяся по какому-то адресу (например 0x000F0010)
int AddrValue=&Value; //теперь в переменной AddrValue хранится значение 0x000F0010
Стоит отметить, что в адресация зависит от разрядности вычислителя.
Указатель (C/C++)
Как уже было сказано у памяти есть некая адресация (смещение относительно начала) за счет чего можно не копировать переменные, массивы и тд в текущие функции, а передавать указатель и «говорить» данные лежат ВООН там! )

Рассмотрим предыдущую таблицу – пусть по адресу 0x013FFF01 лежит переменная типа char Variable=10;
Тогда, мы можем работать с ее адресом
char* pVariable=&Variable; // теперь в pVariable хранится указатель на адрес 0x013FFF01
Что мы сделали
char* – указатель на область в памяти, хранящую переменную типа char
&Variable – тут мы взяли адрес переменной Variable
И просто присвоили одно другому.
Мы можем изменить значение Variable
для этого сделаем операцию разыменования (дописав * перед указателем)
*pVariable=15; //теперь переменная Variable=15
Если создается просто указатель без присвоения значения, то стоит присваивать его NULL/null/nullptr.
NULL/null – просто присвоение к 0
nullptr – ключевое слово, введенное в 11 стандарте С++ для описания нулевого указателя (nullptr !=0)
Указатель – такая же переменная как char, int… и с ней доступны те же самые операции.
Важно! Тип указателя и тип переменной должен быть одинаков, т.е. int* pVariable=&Variable; невозможно сделать.
Стоит отметить, что название массива является указателем на его элемент с индексом [0].
Обычно указатели передаются в функции чтобы не копировать большие объемы данных, например структуры, в этом случае стоит выполнять проверку, что указатель не равен 0!
Можно делать указатель на указатель.
Например: char** pVariable=&pVariable;
Ссылка (C++)
У указателей есть главная проблема – они могут быть равными 0 (неинициализированными), из-за этого приходится постоянно делать проверку, особенно это актуально при работе с динамической памятью.
Также для изменения значения было необходимо выполнять операцию разыменования.
Для упрощения работы в C++ были созданы ссылки.
В ссылках таких понятия нет, так как меняя ссылку вы автоматически меняете и переменную. Ссылки напрямую ссылаются к переменной, поэтому их синтаксис проще:
char Data = 10;
char &Value = Data; // Создание ссылки на переменную
Value =15;
По сути ссылка – готовый переход на адрес в памяти, и при этом этот переход не может быть не инициализирован, что избавляет от многих проверок.
Главный минус ссылки – их нельзя изменить!!! Т.е. при создании ссылки она указывает на зону в памяти (например адрес 0x013FFF01) и изменить этот адрес на 0x013FFF02 мы не сможем.
