Maska (informatyka)
Argumenty funkcjiEdit
W językach programowania, takich jak C, pola bitowe są użytecznym sposobem przekazywania zestawu nazwanych argumentów boolean do funkcji. Na przykład, w graficznym API OpenGL istnieje polecenie glClear()
, które czyści ekran lub inne bufory. Może ona wyczyścić do czterech buforów (bufory koloru, głębi, akumulacji i szablonu), więc autorzy API mogliby kazać jej przyjmować cztery argumenty. Ale wtedy wywołanie tej funkcji wyglądałoby jak
glClear(1,1,0,0); // This is not how glClear actually works and would make for unstable code.
, co nie jest zbyt opisowe. Zamiast tego istnieją cztery zdefiniowane bity pola, GL_COLOR_BUFFER_BIT
, GL_DEPTH_BUFFER_BIT
, GL_ACCUM_BUFFER_BIT
i GL_STENCIL_BUFFER_BIT
, a glClear()
jest zadeklarowane jako
void glClear(GLbitfield bits);
Wtedy wywołanie funkcji wygląda tak
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Wewnętrznie funkcja przyjmująca takie pole bitowe może użyć binarnego and
do wyodrębnienia poszczególnych bitów. Na przykład, implementacja glClear()
może wyglądać następująco:
void glClear(GLbitfield bits) { if ((bits & GL_COLOR_BUFFER_BIT) != 0) { // Clear color buffer. } if ((bits & GL_DEPTH_BUFFER_BIT) != 0) { // Clear depth buffer. } if ((bits & GL_ACCUM_BUFFER_BIT) != 0) { // Clear accumulation buffer. } if ((bits & GL_STENCIL_BUFFER_BIT) != 0) { // Clear stencil buffer. }}
Zaletą tego podejścia jest zmniejszenie narzutu argumentów funkcji. Ponieważ minimalny rozmiar danych to jeden bajt, rozdzielenie opcji na osobne argumenty byłoby marnowaniem siedmiu bitów na argument i zajmowałoby więcej miejsca na stosie. Zamiast tego, funkcje zazwyczaj przyjmują jedną lub więcej 32-bitowych liczb całkowitych, z maksymalnie 32 bitami opcji w każdej z nich. Choć eleganckie, w najprostszej implementacji to rozwiązanie nie jest bezpieczne dla typu. A GLbitfield
jest po prostu zdefiniowane jako unsigned int
, więc kompilator pozwoliłby na bezsensowne wywołanie glClear(42)
lub nawet glClear(GL_POINTS)
. W C++ alternatywą byłoby stworzenie klasy hermetyzującej zestaw argumentów, które glClear mógłby zaakceptować i mógłby być czysto zamknięty w bibliotece.
Odwrotne maskiEdit
Maski są używane z adresami IP w IP ACL (Access Control Lists), aby określić, co powinno być dozwolone, a co odrzucone. Aby skonfigurować adresy IP na interfejsach, maski zaczynają się od 255 i mają duże wartości po lewej stronie: na przykład, adres IP 209.165.202.129 z maską 255.255.255.224. Maski dla IP ACL są odwrotne: na przykład, maska 0.0.0.255. Jest to czasami nazywane maską odwrotną lub maską wieloznaczną. Gdy wartość maski jest rozbita na liczby binarne (0 i 1), wyniki określają, które bity adresu mają być brane pod uwagę przy przetwarzaniu ruchu. 0 oznacza, że bity adresu muszą być brane pod uwagę (dokładne dopasowanie); 1 w masce oznacza „nie obchodzi”. Ta tabela dokładniej wyjaśnia tę koncepcję.
Przykład maski:
adres sieci (ruch, który ma być przetwarzany) 10.1.1.0
maska0.0.0.255
adres sieci (binarny)00001010.00000001.00000001.000000
maska (binarna)00000000.000000.000000.11111111
Na podstawie maski binarnej widać, że pierwsze trzy zestawy (oktety) muszą dokładnie odpowiadać podanemu binarnemu adresowi sieci (00001010.00000001.00000001). Ostatni zestaw liczb składa się z cyfr „don’t cares” (.11111111). Dlatego cały ruch, który zaczyna się od 10.1.1. pasuje, ponieważ ostatni oktet jest „don’t care”. Dlatego, z tą maską, adresy sieciowe 10.1.1.1 do 10.1.1.255 (10.1.1.x) są przetwarzane.
Odejmij normalną maskę od 255.255.255.255 w celu określenia maski odwrotnej ACL. W tym przykładzie maska odwrotna jest określana dla adresu sieciowego 172.16.1.0 z normalną maską 255.255.255.0.
255.255.255.255 – 255.255.255.0 (normalna maska) = 0.0.0.255 (maska odwrotna)
OdpowiednikiACL
Źródło/źródło-wildcard z 0.0.0.0/255.255.255.255 oznacza „dowolne”.
Źródło/wildcard z 10.1.1.2/0.0.0.0 jest takie samo jak „host 10.1.1.2”
Maski obrazówEdit
W grafice komputerowej, gdy dany obraz ma być umieszczony nad tłem, obszary przezroczyste mogą być określone poprzez maskę binarną. W ten sposób dla każdego zamierzonego obrazu istnieją właściwie dwie mapy bitowe: właściwy obraz, w którym niewykorzystanym obszarom nadano wartość piksela ze wszystkimi bitami ustawionymi na 0s, oraz dodatkowa maska, w której odpowiadającym im obszarom obrazu nadano wartość piksela ze wszystkimi bitami ustawionymi na 0s, a obszarom otaczającym wartość wszystkich bitów ustawionych na 1s. W próbce po prawej stronie czarne piksele mają bity o wartości wszystkich zer, a białe piksele mają bity o wartości wszystkich jedynek.
W czasie działania, aby umieścić obraz na ekranie nad tłem, program najpierw maskuje bity piksela ekranu z maską obrazu w żądanych współrzędnych za pomocą operacji bitowego AND. To zachowuje piksele tła obszarów przezroczystych, podczas gdy resetuje zerami bity pikseli, które będą zasłonięte przez nałożony obraz.
Następnie program renderuje bity pikseli obrazu, łącząc je z bitami pikseli tła za pomocą operacji bitowego OR. W ten sposób piksele obrazu są odpowiednio rozmieszczone z zachowaniem pikseli otaczających tło. Rezultatem jest doskonałe połączenie obrazu z tłem.
Ta technika jest używana do malowania kursorów urządzeń wskazujących, w typowych dwuwymiarowych grach wideo dla postaci, pocisków i tak dalej (sprites), dla ikon GUI, oraz dla napisów wideo i innych zastosowań mieszania obrazów.
Although related (due to being used for the same purposes), transparent colors and alpha channels are techniques which do not involve the image pixel mixage by binary masking.
Hash tablesEdit
To create a hashing function for a hash table, often a function is used that has a large domain. Aby utworzyć indeks z wyjścia funkcji, można zastosować modulo, aby zmniejszyć rozmiar dziedziny, aby dopasować rozmiar tablicy; jednak często na wielu procesorach szybciej jest ograniczyć rozmiar tablicy haszującej do potęg dwóch wielkości i zamiast tego użyć maski bitowej.
Przykład zarówno modulo, jak i maskowania w 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; // Handle memory allocation for token_array… char token = "some hashable value"; uint32_t hashed_token = hash_function(token, strlen(token), NUM_BUCKETS); // Using modulo size_t index = hashed_token % MAX_RECORDS; // OR // Using bitmask size_t index = hashed_token & HASH_BITMASK; *(token_array+index) = token; // Free the memory from token_array … return 0;}
.