Побитовое И (&), Побитовое ИЛИ (|), Сложение по модулю два (^)

Битовые операторы выполняют свои расчеты на уровне битов переменных. Они помогают решать широкий круг общих проблем программирования. Хорошую статью по битовым операциям можно найти на Википедии

Побитовое И (&)

В С++ оператор побитового И указывается одиночным амперсандом, он ставится между двумя целыми выражениями. Побитовое И действует на позиции каждого бита, окружающих выражения независимо от того какой из операндов стоит первым, а какой вторым. В соответствии с правилом: если оба входных бита равны 1, результирующий выходной сигнал равен 1, в противном случае выход равен 0. Иллюстрация:

    0  0  1  1    операнд1
    0  1  0  1    операнд2
    ----------
    0  0  0  1    результат (операнд1 & операнд2)

В среде разработки Arduino тип int это 16-битное значение, таким образом оператор побитовое И между двумя int выражениями делает 16 одновременных И операций. Иллюстрация:

    int a =  92;    // в двоичном виде: 0000000001011100
    int b = 101;    // в двоичном виде: 0000000001100101
    int c = a & b;  // результат:    0000000001000100, или 68 в десятичном представлении

Каждый бит значений a и b проходит операцию побитового И, в результате все 16 битов попадают в переменную c, полученное значение будет 01000100, что равносильно 65 в двоичном представлении.
Наиболее часто операция побитового И используется для выбора конкретного бит (или битов) от целого значения, часто называемая маска. См. пример ниже.

Побитовое ИЛИ (|)

Побитовое ИЛИ в C++ обозначается вертикальной чертой, |. Как и оператор &, оператор | работает независимо с каждым битом окружающиъ его чисел. Результат операции побитового ИЛИ двух бит будет 1, если хотя бы один из этих битов 1, иначе резульат будет 0. Другими словами:

    0  0  1  1    операнд1
    0  1  0  1    операнд2
    ----------
    0  1  1  1    (операнд1 | операнд2) - результат

Пример использования операции побитового ИЛИ в фрагменте кода на C++:

    int a =  92;    // в бинарном виде: 0000000001011100
    int b = 101;    // в бинарном виде: 0000000001100101
    int c = a | b;  // результат:    0000000001111101, или 125 в десятичном виде.

Пример программы

Основная область примернения операторов побитовое И/ИЛИ это операции чтение/записи в порт. В микроконтроллерах порт это 8-битовое число, через которое можно получить информацию о состоянии контактов. Записи в порт контролирует все контакты сразу.

PORTD является встроенной константой, которая относится к выходному состоянию цифровых выводов 0,1,2,3,4,5,6,7. Если в каком-то бите установлена 1, значит на выводе состояние HIGH. (Вывод при этом должен быть установлен как выход командой pinMode().) Таким образом, если записать PORTD = B00110001; мы установим выводы 2,3 и 7 в состояние логической 1.

Наш алгоритм будет выглядеть вот так:
  • Получить значение PORTD и очистить биты относящиеся к выводам, значение которые мы хотим изменить (с помощью побитового И).
  • Скомбинировать значение PORTD с нашим новым значением (через операцию побитового ИЛИ).
int i;     // переменная счетчика
int j;

void setup(){
DDRD = DDRD | B11111100; // установить биты направлений для выводов с 2 по 7, оставить нетронутыми для выводов 0 и 1 (xx | 00 == xx)
// это тоже самое что и оператор pinMode(pin, OUTPUT) для выводов с 2 по 7
Serial.begin(9600);
}

void loop(){
for (i=0; i<64; i++){

PORTD = PORTD & B00000011;  // очистить биты с 2 по 7, оставить биты (а занчить и выводы) 0 и 1 неизмененными (xx & 11 == xx)
j = (i << 2);               // сдвинуть переменную на два бита влево к пинам 2 -7, чтобы не затронуть пины 0 и 1
PORTD = PORTD | j;          // скомбинирвать значение порта с новым значением
Serial.println(PORTD, BIN); // для отладки выведем значение порта в терминал
delay(100);
   }
}

побитовое XOR или исключающее ИЛИ (^)

Еще один побитовый оператор, немного похожий на обычное бинарное ИЛИ, но небольшим отлиием - он вернет 0, если оба бита будут равны 1. Обозначается символом ^.

    0  0  1  1    операнд1
    0  1  0  1    операнд2
    ----------
    0  1  1  0    (операнд1 ^ операнд2) - результат

Другими словами, после операции илсключающего ИЛИ будет 1 в том случае, если входные биты различны или оба равны 0.

Пример кода:

    int x = 12;     // в бинарном представлении: 1100
    int y = 10;     // в бинарном представлении: 1010
    int z = x ^ y;  // в бинарном представлении: 0110, или десятчиная 6

Оператор ^ часто используется для переключения (т.е. чтобы изменить 0 на 1 или 1 на 0) каких-либо битов в цифровом представлении. Пример программы для переключения цифрового вывода 5.

void setup(){
DDRD = DDRD | B00100000; // установили цифровой вывод 5 как выход
Serial.begin(9600);
}

void loop(){
PORTD = PORTD ^ B00100000;  // переключили бит 5 (цифровой вывод 5), остальные оставили нетронутыми
delay(100);
}

См. также