Как использовать битовую маску?

Как мне использовать это в C ++?
когда это полезно использовать?
Пожалуйста, приведите пример проблемы, где используется битовая маска, как она на самом деле работает.
Спасибо!

46

Решение

Битовая маскировка «полезна» для использования, когда вы хотите сохранить (и впоследствии извлечь) разные данные в пределах одного значения данных.

Пример приложения, которое я использовал ранее, — представьте, что вы сохраняете значения RGB цвета в 16-битном значении. Итак, что-то похожее на это:

RRRR RGGG GGGB BBBB

Затем вы можете использовать битовую маскировку для получения компонентов цвета следующим образом:

  const unsigned short redMask   = 0xF800;
const unsigned short greenMask = 0x07E0;
const unsigned short blueMask  = 0x001F;

unsigned short lightGray = 0x7BEF;

unsigned short redComponent   = (lightGray & redMask) >> 11;
unsigned short greenComponent = (lightGray & greenMask) >> 5;
unsigned short blueComponent =  (lightGray & blueMask);
26

Другие решения

Вкратце битовая маска помогает манипулировать положением нескольких значений. Здесь есть хороший пример;

Битовые флаги — это метод хранения нескольких значений, которые не являются взаимоисключающими, в одной переменной. Вы, наверное, видели их раньше. Каждый флаг представляет собой битовую позицию, которая может быть включена или выключена. Затем у вас есть куча битовых масок #defined для каждой битовой позиции, чтобы вы могли легко манипулировать ею:

    #define LOG_ERRORS            1  // 2^0, bit 0
#define LOG_WARNINGS          2  // 2^1, bit 1
#define LOG_NOTICES           4  // 2^2, bit 2
#define LOG_INCOMING          8  // 2^3, bit 3
#define LOG_OUTGOING         16  // 2^4, bit 4
#define LOG_LOOPBACK         32  // and so on...

// Only 6 flags/bits used, so a char is fine
unsigned char flags;

// initialising the flags
// note that assigning a value will clobber any other flags, so you
// should generally only use the = operator when initialising vars.
flags = LOG_ERRORS;
// sets to 1 i.e. bit 0

//initialising to multiple values with OR (|)
flags = LOG_ERRORS | LOG_WARNINGS | LOG_INCOMING;
// sets to 1 + 2 + 8 i.e. bits 0, 1 and 3

// setting one flag on, leaving the rest untouched
// OR bitmask with the current value
flags |= LOG_INCOMING;

// testing for a flag
// AND with the bitmask before testing with ==
if ((flags & LOG_WARNINGS) == LOG_WARNINGS)
...

// testing for multiple flags
// as above, OR the bitmasks
if ((flags & (LOG_INCOMING | LOG_OUTGOING))
== (LOG_INCOMING | LOG_OUTGOING))
...

// removing a flag, leaving the rest untouched
// AND with the inverse (NOT) of the bitmask
flags &= ~LOG_OUTGOING;

// toggling a flag, leaving the rest untouched
flags ^= LOG_LOOPBACK;**

ВНИМАНИЕ: НЕ используйте оператор равенства (то есть bitflags == bitmask)
для проверки, если установлен флаг — это выражение будет истинным, только если
этот флаг установлен, а все остальные не установлены. Чтобы проверить на один флаг
вам нужно использовать & и ==:

**

if (flags == LOG_WARNINGS) //DON'T DO THIS
...
if ((flags & LOG_WARNINGS) == LOG_WARNINGS) // The right way
...
if ((flags & (LOG_INCOMING | LOG_OUTGOING)) // Test for multiple flags set
== (LOG_INCOMING | LOG_OUTGOING))
...

Вы также можете искать C ++ Triks

97

Допустим, у меня есть 32-битное значение ARGB с 8-битным на канал. Я хочу заменить альфа-компонент другим альфа-значением, например 0x45

unsigned long alpha = 0x45
unsigned long pixel = 0x12345678;
pixel = ((pixel & 0x00FFFFFF) | (alpha << 24));

Маска превращает верхние 8 бит в 0, где было старое альфа-значение. Альфа-значение сдвигается до конечных битовых позиций, которые он займет, а затем ИЛИ в значение маскированного пикселя. Окончательный результат 0x45345678, который сохраняется в пикселях.

3

Битовые маски используются, когда вы хотите закодировать несколько слоев информации в один номер.

Таким образом (при условии разрешения файлов Unix), если вы хотите сохранить 3 уровня ограничения доступа (чтение, запись, выполнение), вы можете проверить для каждого уровня, проверив соответствующий бит.

rwx
---
110

110 в базе 2 переводится как 6 в базе 10.

Таким образом, вы можете легко проверить, разрешено ли кому-то, например, Прочитайте файл, указав в поле разрешения нужное разрешение.

псевдокод:

PERM_READ = 4
PERM_WRITE = 2
PERM_EXEC = 1

user_permissions = 6

if (user_permissions & PERM_READ == TRUE) then
// this will be reached, as 6 & 4 is true
fi

Вам нужно рабочее понимание двоичного представления чисел и логических операторов, чтобы понять битовые поля.

3
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector