← Назад к вопросам

Как получить число со всеми нулями и единицей в определенном разряде?

2.7 Senior🔥 211 комментариев
#Linux и операционные системы#Qt и GUI#STL контейнеры и алгоритмы

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как получить число со всеми нулями и единицей в определённом разряде

Задача

Получить число, где все биты равны 0, кроме одного бита на позиции n, который равен 1.

Например, для позиции 3 в 8-битном числе результат должен быть: 00001000 (8 в десятичной)

Решение: битовый сдвиг

Простейший способ — сдвинуть единицу на нужную позицию:

#include <iostream>
using namespace std;

int main() {
    // Получить число с единицей в позиции 3
    int result = 1 << 3;  // 1 сдвигаем на 3 позиции влево
    cout << result << endl;  // Выведет: 8
    
    // В двоичном: 0001 -> 1000
    printf("%08b\n", result);  // Выведет: 00001000
    
    return 0;
}

Объяснение

Оператор << (левый битовый сдвиг):

  • x << n означает: сдвинуть все биты числа x влево на n позиций
  • Новые позиции справа заполняются нулями
Сдвиг влево на 3:
  1 = 0001
1 << 3 = 1000 = 8

Примеры для разных типов данных

#include <cstdint>
#include <iostream>

int main() {
    // 8-битное число (unsigned char)
    uint8_t bit0 = 1 << 0;   // 00000001 = 1
    uint8_t bit2 = 1 << 2;   // 00000100 = 4
    uint8_t bit7 = 1 << 7;   // 10000000 = 128
    std::cout << "8-bit: " << (int)bit7 << std::endl;  // 128
    
    // 16-битное число (unsigned short)
    uint16_t bit10 = 1 << 10;  // 0000010000000000 = 1024
    std::cout << "16-bit: " << bit10 << std::endl;  // 1024
    
    // 32-битное число (unsigned int)
    uint32_t bit20 = 1u << 20;  // Бит в позиции 20
    std::cout << "32-bit: " << bit20 << std::endl;  // 1048576
    
    // 64-битное число (unsigned long long)
    uint64_t bit63 = 1ull << 63;  // Старший бит
    std::cout << "64-bit: " << bit63 << std::endl;
    
    return 0;
}

Практические применения

1. Установка флага (бита) в числе

// Установить бит n в числе x
uint32_t flags = 0;
int bit_position = 5;
flags |= (1 << bit_position);  // Установить бит 5
// flags теперь: xxxxx1xxxx (бит 5 = 1)

2. Проверка флага

// Проверить установлен ли бит n
if ((flags & (1 << 5)) != 0) {
    std::cout << "Bit 5 is set" << std::endl;
}

3. Очистка флага

// Очистить бит n
flags &= ~(1 << 5);  // Очистить бит 5
// flags теперь: xxxxx0xxxx (бит 5 = 0)

4. Переключение флага

// Переключить бит n (0->1 или 1->0)
flags ^= (1 << 5);  // Toggle бит 5

Функция для удобства

#include <cstdint>

// Создать число с единицей в позиции bit_pos
inline uint32_t make_mask(int bit_pos) {
    return 1u << bit_pos;
}

// Установить бит
inline uint32_t set_bit(uint32_t value, int bit_pos) {
    return value | (1u << bit_pos);
}

// Проверить бит
inline bool test_bit(uint32_t value, int bit_pos) {
    return (value & (1u << bit_pos)) != 0;
}

// Очистить бит
inline uint32_t clear_bit(uint32_t value, int bit_pos) {
    return value & ~(1u << bit_pos);
}

// Переключить бит
inline uint32_t toggle_bit(uint32_t value, int bit_pos) {
    return value ^ (1u << bit_pos);
}

int main() {
    uint32_t value = 0;
    
    // Установить биты 3, 5, 7
    value = set_bit(value, 3);  // 00001000
    value = set_bit(value, 5);  // 00101000
    value = set_bit(value, 7);  // 10101000 = 168
    
    std::cout << value << std::endl;  // 168
    std::cout << test_bit(value, 5) << std::endl;  // 1 (true)
    std::cout << test_bit(value, 4) << std::endl;  // 0 (false)
    
    return 0;
}

Частые ошибки

Ошибка 1: забыть u для unsigned

// ПЛОХО (может быть undefined для больших чисел)
int x = 1 << 31;  // Signed shift, UB!

// ХОРОШО
uint32_t x = 1u << 31;  // Unsigned shift, safe

Ошибка 2: сдвиг на число, больше чем размер типа

// ПЛОХО: undefined behavior
uint8_t x = 1 << 10;  // Сдвиг на 10, но uint8_t только 8 бит

// ХОРОШО: сдвиг в пределах размера типа
uint32_t x = 1u << 10;  // OK, uint32_t имеет 32 бита

Ошибка 3: забыть про приоритет операций

// ПЛОХО: & имеет ниже приоритет чем <<
if (x & 1 << 5) {  // Интерпретируется как: x & (1 << 5)? Нет!
    // Это вычисляет: (x & 1) << 5
}

// ХОРОШО: используй скобки
if (x & (1 << 5)) {
    // Это вычисляет: x & (1 << 5)
}

Битовые флаги в реальных проектах

// Пример: регистр CPU состояния с битовыми флагами
class RegisterStatus {
private:
    uint32_t value = 0;
    
public:
    // Флаг 0: Zero (результат = 0)
    bool is_zero() const { return value & (1 << 0); }
    void set_zero() { value |= (1 << 0); }
    
    // Флаг 1: Carry (был перенос)
    bool has_carry() const { return value & (1 << 1); }
    void set_carry() { value |= (1 << 1); }
    
    // Флаг 2: Overflow (переполнение)
    bool has_overflow() const { return value & (1 << 2); }
    void set_overflow() { value |= (1 << 2); }
};

Итого

Ответ на вопрос:

uint32_t mask = 1 << n;  // n-я позиция, остальное нули

Применение:

  • Установить флаг: x |= (1 << n)
  • Проверить флаг: if (x & (1 << n))
  • Очистить флаг: x &= ~(1 << n)
  • Переключить: x ^= (1 << n)