Битовые операции в C++: Как установить, сбросить и переключить бит

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Битовые операции в C++: Как установить, сбросить и переключить один бит (и не сойти с ума)

Привет, коллега! Если ты когда-нибудь смотрел на чужой код на C++ и видел странные символы вроде |, & и ~, а потом задавался вопросом «зачем они это делают?» — ты по адресу. Сегодня мы разберём одну из самых популярных (и, честно говоря, самых элегантных) тем в программировании: битовые операции. А именно — как установить, сбросить и переключить один бит.

Это не просто академическое упражнение. Работа с битами — это суперсила, которая пригодится тебе везде: от работы с флагами конфигурации и периферией микроконтроллеров до оптимизации хранения данных в играх или базах данных. На Stack Overflow этот вопрос набрал сотни тысяч просмотров — значит, он реально важен.

Давай без скучной теории — сразу к делу. Поехали!

Почему мы вообще работаем с битами?

Представь, что у тебя есть 8 разных настроек (например, включить звук, отображать подсказки, включить ночной режим и т.д.). Можно хранить их в восьми отдельных переменных типа bool. Но это 8 байт (а то и больше). А можно использовать один байт — 8 бит, каждый из которых отвечает за свою настройку. Экономия памяти в 8 раз — и это только начало.

Битовые операции — это низкоуровневая магия, которая работает невероятно быстро. Процессор выполняет их за один такт. Для встраиваемых систем, драйверов и высоконагруженных приложений это критично.

В C++ для работы с битами используются три главных оператора:

  • | (побитовое ИЛИ) — чтобы установить бит.
  • & (побитовое И) — чтобы сбросить бит.
  • ^ (побитовое исключающее ИЛИ, XOR) — чтобы переключить бит.

И ещё один полезный оператор — ~ (побитовое НЕ), который инвертирует все биты. Он нам пригодится для сброса.

Нумерация битов: договоримся сразу

В программировании биты принято нумеровать с нуля. Самый младший бит (Least Significant Bit, LSB) — это бит 0. Самый старший (Most Significant Bit, MSB) — это бит 7 для байта, 15 для слова (16 бит) и т.д.

В этой статье мы будем использовать uint8_t (8-битное беззнаковое целое) для наглядности. Но все примеры работают и с int, unsigned int, uint32_t и любыми другими целочисленными типами.

Как установить бит (Set bit)

Установить бит — значит сделать его равным 1, независимо от того, каким он был раньше.

Самый простой способ — использовать побитовое ИЛИ с маской. Маска — это число, в котором установлен только тот бит, который мы хотим изменить.

Формула:

число |= (1 << номер_бита);

Разберём по шагам:

  1. 1 << номер_бита — сдвигаем единицу влево на нужное количество позиций. Если номер бита = 3, то 1 << 3 даёт двоичное 00001000.
  2. число | маска — операция ИЛИ установит бит в 1, если он был 0, и оставит 1, если он уже был 1.

Пример кода на C++:

#include <iostream>
#include <cstdint>

int main() {
    uint8_t flags = 0b00000000;  // Изначально все биты сброшены

    // Устанавливаем 3-й бит (считаем с нуля)
    flags |= (1 << 3);

    // Теперь flags = 0b00001000
    std::cout << "После установки бита 3: " << static_cast<int>(flags) << std::endl;

    // Устанавливаем 0-й бит
    flags |= (1 << 0);
    // flags = 0b00001001
    std::cout << "После установки бита 0: " << static_cast<int>(flags) << std::endl;

    return 0;
}

Важно: Если ты работаешь с int (который обычно 32-битный), не пытайся сдвинуть единицу на 32 или более позиций — это неопределённое поведение (undefined behavior). Для 32-битного числа максимум — сдвиг на 31.

Как сбросить бит (Clear bit)

Сбросить бит — значит сделать его равным 0.

Здесь уже нужно два оператора: побитовое И и побитовое НЕ.

Формула:

число &= ~(1 << номер_бита);

Разбор полётов:

  1. 1 << номер_бита — создаём маску, как и раньше.
  2. ~(маска) — инвертируем все биты маски. Если маска была 00001000, то ~маска будет 11110111. Все биты, кроме нужного, стали единицами, а нужный — нулём.
  3. число & инвертированная_маска — операция И сбросит нужный бит в 0, а все остальные оставит без изменений.

Пример кода на C++:

#include <iostream>
#include <cstdint>

int main() {
    uint8_t flags = 0b11111111;  // Все биты установлены

    // Сбрасываем 3-й бит
    flags &= ~(1 << 3);

    // Теперь flags = 0b11110111
    std::cout << "После сброса бита 3: " << static_cast<int>(flags) << std::endl;

    // Сбрасываем 0-й бит
    flags &= ~(1 << 0);
    // flags = 0b11110110
    std::cout <<                

Блоги

Рекомендаций по книгам