Что такое бит-маска?

Я новичок в программировании на С, и я столкнулся с битовой маскировкой. Может ли кто-нибудь объяснить мне общую концепцию и функцию маскировки бит? Примеры очень ценятся.

Ответ 1

Маска определяет, какие биты вы хотите сохранить, и какие биты вы хотите очистить.

Маскировка - это действие применения маски к значению. Это достигается тем, что:

  • Побитовое ANDing для извлечения подмножества бит в значении
  • Побитовое ORing для установки подмножества бит в значении
  • Побитовое XORing для переключения подмножества бит в значение

Ниже приведен пример извлечения подмножества бит в значении:

Mask:   00001111b
Value:  01010101b

Применение маски к значению означает, что мы хотим очистить первые (более высокие) 4 бита и сохранить последние (более низкие) 4 бита. Таким образом, мы извлекли более низкие 4 бита. Результат:

Mask:   00001111b
Value:  01010101b
Result: 00000101b

Маскировка выполняется с использованием AND, поэтому в C мы получаем:

uint8_t stuff(...) {
  uint8_t mask = 0x0f;   // 00001111b
  uint8_t value = 0x55;  // 01010101b
  return mask & value;
}

Вот довольно распространенный прецедент: извлечение отдельных байтов из большего слова. Мы определяем старшие биты в слове как первый байт. Для этого мы используем два оператора: & и >> (сдвиг вправо). Так мы можем извлечь четыре байта из 32-разрядного целого числа:

void more_stuff(uint32_t value) {             // Example value: 0x01020304
    uint32_t byte1 = (value >> 24);           // 0x01020304 >> 24 is 0x01 so
                                              // no masking is necessary
    uint32_t byte2 = (value >> 16) & 0xff;    // 0x01020304 >> 16 is 0x0102 so
                                              // we must mask to get 0x02
    uint32_t byte3 = (value >> 8)  & 0xff;    // 0x01020304 >> 8 is 0x010203 so
                                              // we must mask to get 0x03
    uint32_t byte4 = value & 0xff;            // here we only mask, no shifting
                                              // is necessary
    ...
}

Обратите внимание, что вы можете переключить порядок операторов выше, вы можете сначала сделать маску, затем сдвиг. Результаты те же, но теперь вам придется использовать другую маску:

uint32_t byte3 = (value & 0xff00) >> 8;

Ответ 2

Маскировка означает сохранение/изменение/удаление нужной части информации. Давайте посмотрим на операцию маскировки изображения; like- эта операция маскирования удаляет все, что не является skin-

enter image description here

Мы делаем операцию И в этом примере. Есть и другие маскировки operators- ИЛИ, XOR.


Битовая маскировка означает наложение маски на биты. Вот немного маскировки с AND-

     1 1 1 0 1 1 0 1   [input]
(&)  0 0 1 1 1 1 0 0    [mask]
------------------------------
     0 0 1 0 1 1 0 0  [output]

Таким образом, остаются только средние 4 бита (поскольку эти биты равны 1 в этой маске).

Давайте посмотрим на это с XOR-

     1 1 1 0 1 1 0 1   [input]
(^)  0 0 1 1 1 1 0 0    [mask]
------------------------------
     1 1 0 1 0 0 0 1  [output]

Теперь средние 4 бита перевернуты (1 стал 0, 0 стал 1).


Таким образом, используя битовую маску, мы можем получить доступ к отдельным битам [ примеры ]. Иногда этот метод также может быть использован для повышения производительности. Возьми это за example-

bool isOdd(int i) {
    return i%2;
}

Эта функция сообщает, является ли целое число нечетным/четным. Мы можем достичь того же результата с большей эффективностью, используя битовую маску

bool isOdd(int i) {
    return i&1;
}

Краткое объяснение: Если младший бит двоичного числа равен 1 то он нечетен; для 0 это будет даже. Итак, выполняя AND с 1 мы удаляем все остальные биты, кроме младшего значащего бита, т.е.

     55  ->  0 0 1 1 0 1 1 1   [input]
(&)   1  ->  0 0 0 0 0 0 0 1    [mask]
---------------------------------------
      1  <-  0 0 0 0 0 0 0 1  [output]