Как в C++ получить число, где все биты нулевые, кроме одного заданного разряда?

«Как в C++ получить число, где все биты нулевые, кроме одного заданного разряда?» — вопрос из категории C++ Core, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Для создания битовой маски с единицей в заданной позиции используется оператор левого сдвига (<<).

Базовый пример:

#include <iostream>
#include <cstdint> // Для точных типов

int main() {
    int bit_position = 3; // Нумерация с 0 (младший бит)
    int mask = 1 << bit_position; // 1 << 3 = 0b1000 (десятичное 8)
    std::cout << "Mask (dec): " << mask << std::endl; // 8
    std::cout << "Mask (hex): 0x" << std::hex << mask << std::endl; // 0x8

    // Использование для проверки бита в числе
    int value = 13; // 0b1101
    bool is_bit_set = (value & mask) != 0;
    std::cout << "Bit at position " << bit_position << " is " << (is_bit_set ? "set" : "not set") << std::endl;
    return 0;
}

Критически важные нюансы:

  1. Переполнение и неопределённое поведение: Сдвиг на позицию, большую или равную ширине типа, приводит к UB.
    int x = 1 << 32; // UB для 32-битного int!
  2. Используйте беззнаковые типы: Для битовых операций всегда предпочтительнее беззнаковые типы, так как сдвиги знаковых чисел могут иметь платформо-зависимое поведение.
    unsigned int safe_mask = 1U << bit_position;
  3. Для 64-битных масок: Используйте суффикс ULL.
    uint64_t wide_mask = 1ULL << 45; // Безопасно для позиций > 31
  4. Портируемый способ с проверкой:
    
    #include <climits>

template T make_bitmask(unsigned int pos) { if (pos >= sizeof(T) * CHAR_BIT) { return 0; // Или выбросить исключение } return static_cast(T{1} << pos); } // Использование: auto mask32 = make_bitmask(5); auto mask64 = make_bitmask(40);