Как мне использовать это в C ++?
когда это полезно использовать?
Пожалуйста, приведите пример проблемы, где используется битовая маска, как она на самом деле работает.
Спасибо!
Битовая маскировка «полезна» для использования, когда вы хотите сохранить (и впоследствии извлечь) разные данные в пределах одного значения данных.
Пример приложения, которое я использовал ранее, — представьте, что вы сохраняете значения 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);
Вкратце битовая маска помогает манипулировать положением нескольких значений. Здесь есть хороший пример;
Битовые флаги — это метод хранения нескольких значений, которые не являются взаимоисключающими, в одной переменной. Вы, наверное, видели их раньше. Каждый флаг представляет собой битовую позицию, которая может быть включена или выключена. Затем у вас есть куча битовых масок #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
Допустим, у меня есть 32-битное значение ARGB с 8-битным на канал. Я хочу заменить альфа-компонент другим альфа-значением, например 0x45
unsigned long alpha = 0x45
unsigned long pixel = 0x12345678;
pixel = ((pixel & 0x00FFFFFF) | (alpha << 24));
Маска превращает верхние 8 бит в 0, где было старое альфа-значение. Альфа-значение сдвигается до конечных битовых позиций, которые он займет, а затем ИЛИ в значение маскированного пикселя. Окончательный результат 0x45345678, который сохраняется в пикселях.
Битовые маски используются, когда вы хотите закодировать несколько слоев информации в один номер.
Таким образом (при условии разрешения файлов 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
Вам нужно рабочее понимание двоичного представления чисел и логических операторов, чтобы понять битовые поля.