В информатике маска или битовая маска — это данные, которые используются для побитовых операций , в частности, в битовом поле . Используя маску, несколько бит в байте , полубайте , слове и т. д. могут быть включены или выключены, или инвертированы из включенного в выключенное (или наоборот) в одной побитовой операции. Дополнительное использование маскирования включает предикацию в векторной обработке , где битовая маска используется для выбора того, какие операции с элементами в векторе должны быть выполнены (бит маски включен), а какие нет (бит маски очищен).
Чтобы включить определенные биты, можно использовать побитовую операцию, следуя OR
принципу , что Y OR 1 = 1
и Y OR 0 = Y
. Таким образом, чтобы убедиться, что бит включен, OR
можно использовать с 1
. Чтобы оставить бит неизменным, OR
используется с 0
.
Пример: Маскирование старшего полубайта (биты 4, 5, 6, 7) при сохранении младшего полубайта (биты 0, 1, 2, 3) без изменений .
1001 0101 1010 0101 ИЛИ 1111 0000 1111 0000 = 1111 0101 1111 0101
Чаще на практике биты "маскируются " (или маскируются в 0
), чем "маскируются в " (или маскируются в 1
). Когда бит редактируется AND
с 0, результатом всегда будет 0, т.е. Y AND 0 = 0
. Чтобы оставить другие биты такими, какими они были изначально, их можно AND
редактировать с 1
помощьюY AND 1 = Y
Пример: Маскирование старшего полубайта ( биты 4, 5, 6, 7) при сохранении младшего полубайта (биты 0, 1, 2, 3) без изменений.
1001 0101 1010 0101И 0000 1111 0000 1111 = 0000 0101 0000 0101
Можно использовать битовые маски для легкой проверки состояния отдельных битов независимо от других битов. Для этого отключение всех остальных битов с помощью побитовой операции AND
выполняется так, как обсуждалось выше, и значение сравнивается с 0
. Если оно равно 0
, то бит был выключен, но если значение равно любому другому значению, то бит был включен. Удобство этого заключается в том, что не нужно выяснять, что на самом деле представляет собой значение, достаточно того, что оно не является 0
.
Пример: запрос статуса 4-го бита
1001 1 101 1001 0 101И 0000 1 000 0000 1 000 = 0000 1 000 0000 0 000
До сих пор в статье рассматривалось, как включать и выключать биты, но не то и другое одновременно. Иногда не имеет значения, какое значение, но его нужно сделать противоположным текущему. Этого можно добиться с помощью операции XOR
(исключающее или) . XOR
возвращает 1
только в том случае, если нечетное количество бит равно 1
. Следовательно, если два соответствующих бита равны 1
, результатом будет 0
, но если только один из них равен 1
, результатом будет 1
. Следовательно, инверсия значений битов выполняется путем XOR
их замены на 1
. Если исходный бит был 1
, возвращается 1 XOR 1 = 0
. Если исходный бит был , 0
возвращается 0 XOR 1 = 1
. Также обратите внимание, что XOR
маскирование является бит-безопасным, то есть оно не повлияет на немаскированные биты, поскольку Y XOR 0 = Y
, как и OR
.
Пример: переключение значений битов
10011101 10010101XOR 00001111 11111111 = 10010010 01101010
Чтобы записать произвольные единицы и нули в подмножество битов, сначала запишите нули в это подмножество, а затем установите старшие биты:
регистр = (регистр & ~битовая маска) | значение;
В таких языках программирования, как C , битовые поля являются полезным способом передачи набора именованных булевых аргументов в функцию. Например, в графическом API OpenGL есть команда, glClear()
которая очищает экран или другие буферы. Она может очищать до четырех буферов (буферы цвета, глубины, накопления и трафарета ), поэтому авторы API могли бы заставить ее принимать четыре аргумента. Но тогда вызов к ней будет выглядеть как
glClear ( 1 , 1 , 0 , 0 ); // На самом деле glClear работает не так, и это приведет к нестабильному коду.
что не очень наглядно. Вместо этого есть четыре определенных бита поля, GL_COLOR_BUFFER_BIT
, GL_DEPTH_BUFFER_BIT
, GL_ACCUM_BUFFER_BIT
, и GL_STENCIL_BUFFER_BIT
и glClear()
объявлено как
void glClear ( биты битового поля GL );
Тогда вызов функции выглядит так
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
Внутри функция, принимающая битовое поле, как это, может использовать двоичный код and
для извлечения отдельных битов. Например, реализация glClear()
может выглядеть так:
void glClear ( GLbitfield bits ) { if (( bits & GL_COLOR_BUFFER_BIT ) != 0 ) { // Очистить буфер цвета. } if (( bits & GL_DEPTH_BUFFER_BIT ) != 0 ) { // Очистить буфер глубины. } if (( bits & GL_ACCUM_BUFFER_BIT ) != 0 ) { // Очистить буфер накопления. } if (( bits & GL_STENCIL_BUFFER_BIT ) != 0 ) { // Очистить буфер трафарета. } }
Преимущество этого подхода в том, что уменьшаются накладные расходы на аргументы функций. Поскольку минимальный размер данных составляет один байт, разделение опций на отдельные аргументы приведет к трате семи бит на аргумент и займет больше места в стеке. Вместо этого функции обычно принимают одно или несколько 32-битных целых чисел, с 32 битами опций в каждом. Несмотря на элегантность, в простейшей реализации это решение не является типобезопасным . A GLbitfield
просто определяется как unsigned int
, поэтому компилятор разрешит бессмысленный вызов glClear(42)
или даже glClear(GL_POINTS)
. В C++ альтернативой было бы создание класса для инкапсуляции набора аргументов, которые может принять glClear и которые можно было бы чисто инкапсулировать в библиотеке.
Маски используются с IP-адресами в IP ACL (списках контроля доступа) для указания того, что должно быть разрешено, а что запрещено. Для настройки IP-адресов на интерфейсах маски начинаются с 255 и имеют большие значения с левой стороны: например, IP-адрес 203.0.113.129 с маской 255.255.255.224 . Маски для IP ACL являются обратными: например, маска 0.0.0.255 . Иногда это называется обратной маской или маской с подстановочными знаками . Когда значение маски разбивается на двоичные числа (0 и 1), результаты определяют, какие биты адреса следует учитывать при обработке трафика. Бит 0 указывает, что бит адреса необходимо учитывать (точное совпадение); бит 1 в маске означает «неважно». Эта таблица дополнительно объясняет концепцию.
Пример маски:
сетевой адрес (трафик, который подлежит обработке): 192.0.2.0
маска: 0.0.0.255
сетевой адрес (двоичный): 11000000.00000000.00000010.00000000
маска (двоичная): 00000000.00000000.00000000.11111111
На основе двоичной маски видно, что первые три набора ( октета ) должны точно соответствовать заданному двоичному сетевому адресу (11000000.00000000.00000010). Последний набор чисел состоит из "don't cares" (.11111111). Следовательно, весь трафик, начинающийся с " 192.0.2. ", совпадает, так как последний октет - "don't care". Следовательно, с этой маской обрабатываются сетевые адреса с 192.0.2.1 по 192.0.2.255 ( 192.0.2.x ).
Вычтите нормальную маску из 255.255.255.255 , чтобы определить обратную маску ACL. В этом примере обратная маска определяется для сетевого адреса 198.51.100.0 с нормальной маской 255.255.255.0 .
255.255.255.255 - 255.255.255.0 (нормальная маска) = 0.0.0.255 (обратная маска)
Эквиваленты ACL
Источник/подстановочный знак источника 0.0.0.0 / 255.255.255.255 означает «любой».
Источник/подстановочный знак 198.51.100.2 / 0.0.0.0 такой же, как и «хост 198.51.100.2 ».
В компьютерной графике , когда заданное изображение должно быть размещено на фоне, прозрачные области могут быть указаны с помощью бинарной маски. [1] Таким образом, для каждого предполагаемого изображения фактически есть два битовых массива : фактическое изображение, в котором неиспользуемым областям дано значение пикселя со всеми битами, установленными в 0, и дополнительная маска , в которой соответствующим областям изображения дано значение пикселя со всеми битами, установленными в 0, а окружающим областям — значение всех битов, установленных в 1. В примере справа черные пиксели имеют все нулевые биты, а белые пиксели имеют все единичные биты.
Во время выполнения , чтобы поместить изображение на экран поверх фона, программа сначала маскирует биты пикселя экрана маской изображения в нужных координатах, используя побитовую операцию И. Это сохраняет фоновые пиксели прозрачных областей, в то время как биты пикселей, которые будут скрыты перекрывающимся изображением, сбрасываются нулями.
Затем программа визуализирует биты пикселя изображения, объединяя их с битами пикселя фона с помощью побитовой операции ИЛИ . Таким образом, пиксели изображения размещаются соответствующим образом, сохраняя окружающие пиксели фона. Результатом является идеальное соединение изображения с фоном.
Эта техника используется для рисования курсоров указывающих устройств, в типичных 2-D видеоиграх для персонажей, пуль и т. д. (спрайты ) , для иконок GUI , а также для титров видео и других приложений смешивания изображений. Более быстрый метод — просто перезаписать пиксели фона пикселями переднего плана, если их альфа=1
Хотя прозрачные цвета и альфа-каналы связаны (поскольку используются для одних и тех же целей), они представляют собой методы, которые не подразумевают смешивание пикселей изображения посредством бинарной маскировки.
Чтобы создать функцию хеширования для хеш-таблицы , часто используется функция с большим доменом. Чтобы создать индекс из выходных данных функции, можно взять модуль, чтобы уменьшить размер домена до размера массива; однако на многих процессорах часто быстрее ограничить размер хеш-таблицы степенями двух и вместо этого использовать битовую маску.
Пример использования модуля и маскирования на языке C:
#include <stdint.h> #include <string.h> int main ( void ) { const uint32_t NUM_BUCKETS = 0xFFFFFFFF ; // 2^32 - 1 const uint32_t MAX_RECORDS = 1 << 10 ; // 2^10 const uint32_t HASH_BITMASK = 0x3FF ; // (2^10)-1 char ** token_array = NULL ; // Обработка выделения памяти для token_array… char token [] = "некоторое хешируемое значение" ; uint32_t hashed_token = hash_function ( token , strlen ( token ), NUM_BUCKETS ); // Используем модуль size_t index = hashed_token % MAX_RECORDS ; // ИЛИ // Используем битовую маску size_t index = hashed_token & HASH_BITMASK ; * ( массив_токенов + индекс ) = токен ; // Освобождаем память из token_array … return 0 ; }