Маскування (програмування)
Маскувáння (англ. mask, masking) — в інформатиці — спосіб обробки даних на бітовому рівні, для одержання значення якогось біта або набору бітів з числа, слова або байта. Маскування виконують з використанням логічних операцій та потрібним набором бітів — маскою.
Маска або бітова маска — дані, використовувані для побітових операцій, зокрема в бітовому полі. Використовуючи маску, кілька бітів у байті, півбайті, слові тощо можна ввімкнути або вимкнути, або інвертувати з увімкнення на вимкнення (або навпаки) за допомогою однієї побітової операції. Також маскування використовують для предикації[en] в обробці векторів, де бітова маска забезпечує вибір того, виконується операція з елементами вектора (біт маски ввімкнено), чи ні (біт маски вимкнено).
Назва походить від аналогії з простим шифруванням, коли маска з отворами, накладена на беззмістовний текст, відкриває лише потрібні букви.
Щоб увімкнути певні біти, можна використати порозрядну операцію АБО (OR)
, завдяки тому, що для окремого біта Y Y OR 1 = 1
і Y OR 0 = Y
. Тому, щоб забезпечити стан біта 1, слід виконати OR
з 1
. Щоб залишити біт без змін, OR
виконуємо з 0
.
Приклад: вимкнення старшого нібла (біти 4, 5, 6, 7), але залишення молодшого нібла (біти 0, 1, 2, 3) без змін.
10010101 10100101 OR 11110000 11110000 = 11110101 11110101
Частіше на практиці біти «вимикають» (або маскують у 0
). Якщо до біта застосувати операцію І (AND
) з 0, результат завжди дорівнює 0, тобто Y AND 0 = 0
. Щоб залишити інші біти незміненими, над ними слід виконати AND
з 1
, оскільки Y AND 1 = Y
Приклад: маскування старшого нібла (біти 4, 5, 6, 7), залишаючи молодший нібл (біти 0, 1, 2, 3) без змін.
10010101 10100101 AND 00001111 00001111 = 00000101 00000101
За допомогою бітової маски легко перевірити стан окремого біта. Для цього всі інші біти вимикаємо за допомогою порозрядного AND
як описано вище, і значення порівнюємо з 0
. Якщо воно дорівнює 0
, то біт був вимкнений, але якщо воно відмінне від 0
, то біт був увімкненим. Зручно, що немає необхідності з'ясовувати, яке насправді значення отримано, достатньо того, що воно не дорівнює 0
.
Приклад: запит статусу 4-го біта
10011101 10010101 AND 00001000 00001000 = 00001000 00000000
Іноді, незалежно від значення біта, його потрібно зробити протилежним до поточного (інвертувати). Цього можна досягти за допомогою операції 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 10010101 XOR 00001111 11111111 = 10010010 01101010
Щоб записати довільні 1 і 0 до підмножини бітів, спочатку запишіть 0 до цієї підмножини, а потім встановіть старші біти:
register = (register & ~bitmask) | value;

У мовах програмування, таких як C, бітові поля — це корисний спосіб передавання набору іменованих булівських аргументів у функцію. Наприклад, у графічному API OpenGL є команда glClear()
яка очищає екран або інші буфери. Вона може очистити до чотирьох буферів (буфер кольору, глибини, накопичення та шаблону), тому автори API могли мати чотири аргументи. Але тоді виклик функції виглядав би так
що не дуже наочно. Натомість є чотири визначені біти поля: GL_COLOR_BUFFER_BIT
, GL_DEPTH_BUFFER_BIT
, GL_ACCUM_BUFFER_BIT
і GL_STENCIL_BUFFER_BIT
, а glClear()
оголошено як
void glClear(GLbitfield bits);
Тоді виклик функції виглядає так
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 бітових параметрів. Попри елегантність, у найпростішій реалізації це рішення не є типобезпечним. 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. Це іноді називають інверсною маскою або маскою підстановки[en]. Коли значення маски розглядається як двійкове (з 0 і 1), воно визначає, які біти адреси слід враховувати при обробці трафіку. 0 вказує на те, що необхідно враховувати біт адреси (точна відповідність); 1 в масці означає «байдуже». Для пояснення концепції розгляньмо приклад.
Приклад маски:
- мережева адреса (трафік, який потрібно обробити): 192.0.2.0
- маска: 0.0.0.255
- мережева адреса (двійкова): 11000000.00000000.00000010.00000000
- маска (двійкова): 00000000.00000000.00000000.11111111
Виходячи з двійкової маски, можна побачити, що перші три набори (октети) мають точно відповідати заданій двійковій мережевій адресі (11000000.00000000.00000010). Останній набір чисел складається з «байдуже» (.11111111). Отже, увесь трафік, який починається з «192.0.2.», збігається, оскільки останній октет — «байдуже». Тому з цією маскою обробляються мережеві адреси від 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. На малюнку праворуч чорні пікселі мають усі нульові біти, а білі пікселі — всі одиничні біти.
Під час виконання[en], щоб розмістити зображення на екрані поверх тла, програма спочатку маскує біти пікселя екрана в потрібних координатах за допомогою маски зображення та бітової операції І. Це зберігає пікселі тла прозорих ділянок, а біти пікселів, які має закрити зображення, скидає на нуль.
Потім програма візуалізує біти пікселя зображення, поєднуючи їх із бітами пікселя тла за допомогою операції побітового АБО. Завдяки цьому пікселі зображення розміщуються як належить, зберігаючи навколишні пікселі тла. Результат — точне поєднання зображення і тла.

Ця техніка використовується для малювання курсорів вказівних пристроїв, у типових двовимірних відеоіграх для персонажів, куль тощо (спрайтів), для піктограм графічного інтерфейсу користувача, а також для створення заголовків відео та інших програм для змішування зображень. Швидший спосіб — просто перезаписати пікселі тла пікселями переднього плану, якщо їх альфа=1
Хоча прозорі кольори та альфа-канали використовують для тих самих цілей, ці методи не передбачають змішування пікселів зображень за допомогою двійкового маскування.
Щоб створити функцію гешування для геш-таблиці, часто використовують функція, яка має велику область значень. Щоб створити індекс із вихідних даних функції, можна для зменшення розміру області значень відповідно до розміру масиву використати остачі; однак на багатьох процесорах часто швидше обмежити розмір хеш-таблиці розмірами, рівними степеням 2, та замість цього використовувати бітову маску.
Приклад обох підходів на 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[] = "some hashable value";
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+index) = token;
// Вивільняємо пам'ять token_array …
return 0;
}
- Бітове поле[en]
- Бітові операції
- Двійково-десятковий код
- Маніпуляції з бітами[en]
- Маска (значення)
- Регулярний вираз
- umask[en]
- ↑ Mask R-CNN with OpenCV. PyImageSearch (амер.). 19 листопада 2018. Процитовано 5 квітня 2020.
Ця стаття не містить посилань на джерела. (березень 2017) |