Ответ
Битовые операции в C/C++ — это низкоуровневые операции, которые работают непосредственно с отдельными битами целочисленных типов данных (int, char, uint32_t и т.д.). Они выполняются процессором очень быстро и часто используются для оптимизации, управления флагами, работы с аппаратными регистрами или реализации компактных структур данных.
Основные операторы:
| Оператор | Название | Описание | Пример (a=0b1100, b=0b1010) |
|---|---|---|---|
& |
Побитовое И (AND) | Бит результата = 1, если оба соответствующих бита операндов = 1. | a & b = 0b1000 |
| |
Побитовое ИЛИ (OR) | Бит результата = 1, если хотя бы один из битов = 1. | a | b = 0b1110 |
^ |
Исключающее ИЛИ (XOR) | Бит результата = 1, если биты операндов различны. | a ^ b = 0b0110 |
~ |
Побитовое НЕ (NOT) | Инверсия всех битов операнда. | ~a = 0b...11110011 |
<< |
Сдвиг влево (Left Shift) | Сдвигает биты влево, заполняя младшие биты нулями. Эквивалентно умножению на 2^n. | a << 2 = 0b110000 (48) |
>> |
Сдвиг вправо (Right Shift) | Сдвигает биты вправо. Для беззнаковых типов — заполняет старшие биты нулями. Для знаковых — зависит от компилятора (обычно знаковый бит). Эквивалентно целочисленному делению на 2^n. | (unsigned)a >> 2 = 0b0011 (3) |
Практическое применение: работа с набором флагов (битовой маской).
#include <cstdint>
#include <iostream>
// Определяем флаги как степени двойки (один установленный бит)
enum class UserPermissions : uint8_t {
NONE = 0b00000000, // 0
READ = 0b00000001, // 1 << 0
WRITE = 0b00000010, // 1 << 1
EXECUTE = 0b00000100, // 1 << 2
ADMIN = 0b10000000 // 1 << 7
};
int main() {
uint8_t myPermissions = 0;
// Установка флагов (добавление прав) с помощью OR
myPermissions |= static_cast<uint8_t>(UserPermissions::READ);
myPermissions |= static_cast<uint8_t>(UserPermissions::WRITE);
// myPermissions теперь = 0b00000011 (READ + WRITE)
// Проверка наличия флага с помощью AND
bool canWrite = (myPermissions & static_cast<uint8_t>(UserPermissions::WRITE)) != 0; // true
bool isAdmin = (myPermissions & static_cast<uint8_t>(UserPermissions::ADMIN)) != 0; // false
// Снятие флага (сброс бита)
myPermissions &= ~static_cast<uint8_t>(UserPermissions::WRITE); // Убираем право WRITE
// myPermissions теперь = 0b00000001 (только READ)
// Переключение флага (XOR)
myPermissions ^= static_cast<uint8_t>(UserPermissions::EXECUTE); // Добавляем EXECUTE
myPermissions ^= static_cast<uint8_t>(UserPermissions::EXECUTE); // Убираем EXECUTE
std::cout << "Permissions byte: " << std::hex << (int)myPermissions << std::endl;
return 0;
}
Важно: При сдвигах вправо знаковых чисел (int, short) результат зависит от реализации (архитектурно-зависимое поведение). Для переносимости лучше работать с беззнаковыми типами (unsigned int, uint32_t).