& (bitwise AND)
Оператор & сравнивает каждую пару битов двух чисел: результат равен 1 только там, где оба бита равны 1 — удобно для масок и проверки отдельных битов.
Полная статья
Описание
Побитовый AND записывается одиночным амперсандом & и ставится между двумя целочисленными выражениями. Оператор сравнивает каждую пару битов на одинаковых позициях: если оба бита равны 1, результат на этой позиции тоже 1; во всех остальных случаях — 0.
Таблица истинности для одной битовой позиции:
0 0 1 1 operand1
0 1 0 1 operand2
----------
0 0 0 1 (operand1 & operand2) - returned result
Важно не путать & с логическим оператором &&: последний работает с булевыми значениями целиком и возвращает true или false, тогда как & работает побитово и возвращает целое число.
На платах с AVR-архитектурой тип int занимает 16 бит, поэтому операция a & b над двумя значениями int одновременно выполняет 16 независимых операций AND — по одной для каждой позиции.
Пример кода
int a = 92; // в двоичном виде: 0000000001011100
int b = 101; // в двоичном виде: 0000000001100101
int c = a & b; // результат: 0000000001000100, или 68 в десятичном виде.
Здесь каждый из 16 бит переменных a и b обрабатывается независимо. Результат сохраняется в c — в двоичном виде это 01000100, что равно 68 в десятичном.
Маскирование битов
Самое частое применение & — битовая маска: выделить один или несколько нужных битов из числа, обнулив все остальные. Для этого создаётся «маска» — число, в котором стоят единицы ровно на тех позициях, которые вас интересуют.
Например, чтобы проверить, установлен ли третий бит (считая с нуля) в переменной x, достаточно написать x & 0b00001000. Если результат не равен нулю — бит установлен.
Пример с регистрами (зависит от архитектуры AVR):
PORTD = PORTD & 0b00000011; // сбросить биты 2–7, оставить пины PD0 и PD1 нетронутыми (xx & 11 == xx)
Где применяется
- Чтение состояния отдельного пина через регистры — проверить, установлен ли конкретный бит в порту микроконтроллера, не затрагивая остальные.
- Разбор байта протокола — выделить поле флагов из байта, полученного по UART, SPI или I2C.
- Ограничение диапазона значений — быстро «обрезать» число до степени двойки:
value & 0xFFоставляет только младшие 8 бит. - Проверка чётности —
n & 1равно 0 для чётных чисел и 1 для нечётных.
Практические замечания
- Не путайте
&(побитовый AND) и&&(логический AND) — это разные операторы с разным поведением. - Размер типа влияет на результат:
intна AVR — 16 бит, на ARM (Due, Zero, MKR) — 32 бита. Если важна переносимость, используйте типы фиксированной ширины:int16_t,uint8_tи т. д. - При маскировании удобно записывать маску в двоичном виде (
0b00001111) или шестнадцатеричном (0x0F) — так сразу видно, какие биты затронуты. - Результат
&всегда можно вывести в Serial Monitor черезSerial.println(c, BIN), чтобы увидеть двоичное представление и убедиться, что маска работает правильно. - Операция не изменяет исходные переменные — она возвращает новое значение, которое нужно куда-то сохранить или сразу использовать в условии.