^ (bitwise XOR)
Оператор ^ (побитовый XOR) возвращает 1, если биты операндов различаются — удобен для переключения битов и сравнения флагов.
Полная статья
Описание
Побитовый XOR — один из наиболее специфичных операторов C++. Он обозначается символом каретки ^ и работает с каждой парой битов двух целых чисел независимо: если биты различаются (один равен 0, другой равен 1), результирующий бит будет 1. Если биты одинаковые — результат 0.
Главное отличие от обычного OR: XOR не даёт 1, когда оба бита равны 1. Отсюда и название — исключающее ИЛИ.
Таблица истинности для одного бита:
0 0 1 1 operand1
0 1 0 1 operand2
----------
0 1 1 0 (operand1 ^ operand2) - returned result
Пример кода
int x = 12; // двоичное: 1100
int y = 10; // двоичное: 1010
int z = x ^ y; // двоичное: 0110, или десятичное 6
Где применяется
Оператор ^ чаще всего используют в двух ситуациях:
- Переключение (toggle) отдельных битов — удобно для управления несколькими выходами через один регистр или переменную.
- Простое шифрование — XOR с ключом маскирует данные, а повторное применение того же ключа восстанавливает исходное значение.
- Сравнение флагов — быстро выяснить, какие именно биты изменились между двумя состояниями.
- Генерация контрольных сумм — XOR всех байт блока данных даёт простой, но быстрый способ обнаружить одиночную ошибку.
Переключение битов с помощью маски
Самое частое применение ^ в Arduino-скетчах — инвертировать нужные биты, не трогая остальные. Принцип прост: в маске ставим 1 там, где хотим переключить бит, и 0 там, где бит должен остаться без изменений.
// Примечание: этот код использует регистры, специфичные для микроконтроллеров AVR (Uno, Nano, Leonardo, Mega и др.)
// он не скомпилируется для других архитектур
void setup() {
DDRB = DDRB | 0b00100000; // установить PB5 (пин 13 на Uno/Nano, пин 9 на Leonardo/Micro, пин 11 на Mega) как OUTPUT
Serial.begin(9600);
}
void loop() {
PORTB = PORTB ^ 0b00100000; // инвертировать PB5, остальные не трогать
delay(100);
}
Практические замечания
- Оператор
^работает только с целыми типами:int,long,byte,uint8_tи т. д. К числам с плавающей точкой он неприменим. - Не путайте
^с оператором возведения в степень — в C++ такого оператора нет. Для степеней используйте функциюpow(). - Двойное применение XOR с одной и той же маской возвращает исходное значение:
x ^ mask ^ mask == x. Это свойство лежит в основе простого шифрования. - При работе с портами микроконтроллера (например,
PORTB ^= 0b00000001) XOR позволяет переключить состояние вывода без чтения и записи отдельных битов вручную — код получается компактнее и быстрее. - Если результат выглядит неожиданно, выведите значения в
Serial Monitorв двоичном виде (Serial.println(value, BIN)) — так сразу видно, какие биты изменились.