& (reference operator)
Оператор & возвращает адрес переменной в памяти: &x даёт не значение x, а его расположение, которое можно сохранить в указатель и передать в функцию или библиотеку.
Полная статья
Описание
Каждая переменная в программе занимает какое-то место в оперативной памяти микроконтроллера. Оператор взятия адреса & позволяет узнать, по какому именно адресу хранится значение переменной. Если x — это переменная, то выражение &x даёт адрес переменной x в памяти, а не её значение.
Этот адрес можно сохранить в указатель соответствующего типа и затем работать с переменной косвенно — читать или изменять её значение через указатель. Именно так в C/C++ реализуется передача переменной в функцию «по ссылке»: функция получает не копию значения, а адрес оригинала и может его изменить.
Пример кода
int *p; // объявляем указатель на тип данных int
int i = 5;
int result = 0;
p = &i; // теперь 'p' содержит адрес переменной 'i'
result = *p; // 'result' получает значение по адресу, на который указывает 'p'
// то есть получает значение 'i', равное 5
Где применяется
- Передача данных в функцию с возвратом нескольких результатов. Если функция должна вернуть больше одного значения, удобно передать адреса нескольких переменных и записать результаты напрямую в них.
- Работа с массивами и строками. Имя массива в C/C++ уже является указателем на первый элемент, но оператор
&позволяет получить адрес любого конкретного элемента. - Библиотеки и API, принимающие указатели. Многие Arduino-библиотеки (например, для работы с I²C или SPI) принимают буферы через указатель — туда передают
&variableили имя массива. - Отладка через Serial. Можно вывести числовое значение адреса переменной, чтобы убедиться, что указатель настроен правильно.
Практические замечания
- Оператор
&в контексте взятия адреса и оператор&в контексте побитового AND — разные операции. Различить их просто: унарный&стоит перед одним операндом (&x), побитовый — между двумя (a & b). - Адрес переменной имеет тип «указатель на тип переменной». Например, для
int xвыражение&xимеет типint*. - Никогда не сохраняйте адрес локальной переменной и не возвращайте его из функции: после выхода из функции эта переменная перестаёт существовать, и указатель станет недействительным.
- На платах Arduino с небольшим объёмом RAM (например, Uno с 2 КБ) работа с указателями требует аккуратности: случайная запись по неверному адресу может повредить стек или другие переменные и привести к непредсказуемому поведению программы.
- Если скетч ведёт себя странно после добавления кода с указателями, проверьте, не выходит ли запись за границы массива и не используете ли вы адрес уже удалённой переменной.
Примечания и предупреждения
Указатели — одна из тем, которая традиционно вызывает затруднения у начинающих. Большинство скетчей для Arduino можно написать вообще без указателей, и это нормально. Но когда нужно эффективно работать со сложными структурами данных, передавать большие буферы без копирования или использовать продвинутые библиотеки, понимание оператора & и указателей в целом сильно упрощает жизнь.