Логические И, ИЛИ, Исключающее ИЛИ, НЕ (AND, OR, XOR, NOT)
В побитовых операциях значение бита равное 1 рассматривается как логическая истина, а 0 — как ложь.
Эти операции дают совершенно другой результат, чем можно ожидать исходя из обычной математики.
Логическое И (AND, оператор &)
Логическое умножение.
X | Y | X AND Y |
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
Результат дает 1, если все из сравниваемых значений равны 1.
Например, если логически умножить 2 на 4, то получим 0.
2: 0b00000010 4: 0b00000100 ---------- 0: 0b00000000
Логическое ИЛИ (OR, оператор |)
Логическое сложение.
X | Y | X OR Y |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
Результат дает 1, если хотя бы одно из сравниваемых значений равно 1.
Например, если логически сложить 142 и 105, то получим 239
142: 0b10001110 105: 0b01101001 ---------- 239: 0b11101111
Исключающее ИЛИ (XOR, оператор ^)
X | Y | X XOR Y |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
Результат дает 1, если только одно из сравниваемых значений равно 1.
Например, 12 и 53 дадут 57.
12: 0b00001100 53: 0b00110101 ---------- 57: 0b00111001
Логическое НЕ (NOT, оператор ~)
X | NOT X |
0 | 1 |
1 | 0 |
Результат дает 1, если значение было равно 0, и наоборот.
Например, 115 преобразуется в 140.
115: 0b01110011 ---------- 140: 0b10001100
Операции побитового сдвига
Битовый сдвиг влево (оператор <<)
Битовый сдвиг влево сдвигает биты влево, дописывая справа нули. Вышедшие за пределы числа биты отбрасываются.
0b01001011 << 2 == 0b00101100
Для целых чисел операция равносильна умножению на 2.
Битовый сдвиг вправо (оператор >>)
Битовый сдвиг вправо сдвигает биты числа вправо, дописывая слева нули.
0b01001011 >> 2 == 0b00010010
Для целых чисел эта операция равносильна целочисленному делению пополам.
Примеры применения
Нумерация битов идет с права налево, первая позиция имеет номер 0.
Выставить определенный бит в 1
Просто применяем операцию побитового сдвига к единице в нужную нам позицию.
1 << position
В этом случае число 1 в левой части в двоичной системе будет представлено как 0b00000001. Запись просто единицы повышает читаемость кода.
И логически сложем нужное число и число, у которого все биты равны нулю, кроме нужного (начиная с нулевого).
Пример:
Нужно установить бит на позиции 4 в 1.
0b00100100 | (1 << 4) == 0b00100100 | 0b00010000 == 0b00110100
Код (C):
int setbit(const int value, const int position) { return (value | (1 << position)); }
Для установки нескольких бит операцию следует повторить.
Код (C):
value |= (1 << position1) | (1 << position2) | (1 << position3);
Выставить определенный бит в 0
Умножим число на такое, у которого все биты равны единице, кроме бита под нужным номером.
Чтобы получить такую маску, сначала надо создать число с нулями и одной единицей, а потом инвертировать его.
Пример:
Нужно установить бит на позиции 4 в 0.
0b11010011 & ~(1 << 4) == 0b11010011 & ~(0b00010000) == 0b11010011 & 0b11101111 == 0b11000011
Код (C):
int unsetbit(const int value, const int position) { return (value & ~(1 << position)); }
Для установки нескольких бит в 0 операцию создание маски следует повторить.
value &= ~((1 << position1) | (1 << position2) | (1 << position3));
Изменить состояния бита в определенной позиции
Воспользуемся функцией Исключающего ИЛИ к числу, которое состоит из одних нулей и одной единицы на месте нужного бита.
Пример:
Нужно изменить состояния бита в позиции 4.
0b00000011 ^ (1 << 4) == 0b00000011 ^ 0b00010000 == 0b00010011
Код (C):
int switchbit(const int value, const int position) { return (value ^ (1 << position)); }
Для изменения нескольких бит создание маски следует повторить.
value ^= (1 << position1) | (1 << position2) | (1 << position3);
Узнать состояние бита в позиции
Для этого логически умножим наше число на проверочное число, у которого все биты равны нулю, кроме проверяемого (начиная с нулевого).
Пример:
Нужно узнать, выставлен ли бит на позиции 4 в 1.
0b00110100 & (1 << 4) == 0b00110100 & 0b00010000 == 0b0001000 == ИСТИНА 0b00100100 & (1 << 4) == 0b00100100 & 0b00010000 == 0b0000000 == ЛОЖЬ
Код (C):
int checkbit(const int value, const int position) { return ((value & (1 << position)) != 0); }