Maska (výpočetní technika)
Argumenty funkcíUpravit
V programovacích jazycích, jako je C, jsou bitová pole užitečným způsobem, jak funkci předat sadu pojmenovaných logických argumentů. Například v grafickém API OpenGL existuje příkaz glClear()
, který vyčistí obrazovku nebo jiné vyrovnávací paměti. Může vymazat až čtyři vyrovnávací paměti (vyrovnávací paměti barev, hloubky, akumulace a šablony), takže autoři API mohli nechat příkaz přijmout čtyři argumenty. Pak by ale její volání vypadalo jako
glClear(1,1,0,0); // This is not how glClear actually works and would make for unstable code.
což není příliš popisné. Místo toho jsou definovány čtyři bity pole, GL_COLOR_BUFFER_BIT
, GL_DEPTH_BUFFER_BIT
, GL_ACCUM_BUFFER_BIT
a GL_STENCIL_BUFFER_BIT
a glClear()
je deklarováno jako
void glClear(GLbitfield bits);
Pak volání funkce vypadá takto
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Vnitřně může funkce přijímající bitové pole takto použít binární and
pro extrakci jednotlivých bitů. Například implementace glClear()
může vypadat takto:
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. }}
Výhodou tohoto přístupu je, že se sníží režie argumentů funkce. Protože minimální velikost dat je jeden bajt, oddělením možností do samostatných argumentů by se plýtvalo sedmi bity na argument a zabíralo by se více místa na zásobníku. Místo toho funkce obvykle přijímají jedno nebo více 32bitových celých čísel, přičemž v každém z nich je až 32 volitelných bitů. Toto řešení je sice elegantní, ale v nejjednodušší implementaci není typově bezpečné. Znak GLbitfield
je jednoduše definován jako unsigned int
, takže překladač by umožnil nesmyslné volání glClear(42)
nebo dokonce glClear(GL_POINTS)
. V jazyce C++ by alternativou bylo vytvoření třídy, která by zapouzdřila sadu argumentů, které by glClear mohl přijímat a mohl by být čistě zapouzdřen v knihovně.
Inverzní maskyUpravit
Masky se používají s IP adresami v IP ACL (Access Control Lists) k určení toho, co má být povoleno a co zakázáno. Pro konfiguraci IP adres na rozhraních začínají masky číslem 255 a mají velké hodnoty na levé straně: například IP adresa 209.165.202.129 s maskou 255.255.255.224. Masky pro seznamy IP ACL jsou opačné: například maska 0.0.0.255. Někdy se tomu říká inverzní maska nebo maska se zástupnými znaky. Když se hodnota masky rozdělí na binární hodnoty (0 a 1), výsledek určí, které bity adresy se mají brát v úvahu při zpracování provozu. Hodnota 0 znamená, že bity adresy musí být brány v úvahu (přesná shoda); hodnota 1 v masce znamená „je mi to jedno“. Tato tabulka dále vysvětluje tento koncept.
Příklad masky:
síťová adresa (provoz, který má být zpracován) 10.1.1.0
maska0.0.0.255
síťová adresa (binární)00001010.00000001.00000001.00000000
maska (binární)00000000.00000000.00000000.11111111
Na základě binární masky je vidět, že první tři sady (oktety) musí přesně odpovídat dané binární síťové adrese (00001010.00000001.00000001). Poslední sada čísel je tvořena čísly „don’t cares“ (.11111111). Proto veškerý provoz začínající číslem 10.1.1. odpovídá, protože poslední oktet je „don’t care“. S touto maskou se tedy zpracovávají síťové adresy 10.1.1.1 až 10.1.1.255 (10.1.1.x).
Odčítáním normální masky od 255.255.255.255 určíte inverzní masku ACL. V tomto příkladu je inverzní maska určena pro síťovou adresu 172.16.1.0 s normální maskou 255.255.255.0.
255.255.255.255 – 255.255.255.0 (normální maska) = 0.0.0.255 (inverzní maska)
Ekvivalenty ACL
Zdrojová maska 0.0.0.0/255.255.255.255 znamená „libovolná“.
Zdrojová maska 10.1.1.2/0.0.0.0 je stejná jako „hostitel 10.1.1.2“
Obrázkové maskyEdit
V počítačové grafice, pokud je daný obrázek určen k umístění na pozadí, lze průhledné oblasti určit pomocí binární masky. Tímto způsobem existují pro každý zamýšlený obrázek vlastně dvě bitové mapy: skutečný obrázek, ve kterém mají nepoužité oblasti hodnotu pixelu se všemi bity nastavenými na 0, a dodatečná maska, ve které mají odpovídající oblasti obrázku hodnotu pixelu se všemi bity nastavenými na 0 a okolní oblasti hodnotu všech bitů nastavených na 1s. V ukázce vpravo mají černé pixely hodnotu všech nulových bitů a bílé pixely hodnotu všech jedničkových bitů.
Při spuštění, aby se obraz umístil na obrazovku přes pozadí, program nejprve maskuje bity pixelu obrazovky s maskou obrazu na požadovaných souřadnicích pomocí operace bitové AND. Tím se zachovají pixely pozadí průhledných oblastí a zároveň se vynulují bity pixelů, které budou zakryty překrytým obrazem.
Poté program vykreslí bity pixelu obrazu tak, že je zkombinuje s bity pixelu pozadí pomocí operace bitového OR. Tímto způsobem jsou pixely obrázku vhodně umístěny, přičemž okolní pixely pozadí zůstanou zachovány. Výsledkem je dokonalé složení obrázku na pozadí.
Tato technika se používá pro malování kurzorů ukazovacích zařízení, v typických dvourozměrných videohrách pro postavy, střely apod. (sprity), pro ikony grafického uživatelského rozhraní a pro titulkování videa a další aplikace pro míchání obrázků.
Průhledné barvy a alfa kanály jsou sice příbuzné (vzhledem k tomu, že se používají ke stejným účelům), ale jedná se o techniky, které nezahrnují míchání pixelů obrazu pomocí binárního maskování.
Hašovací tabulkyUpravit
K vytvoření hašovací funkce pro hašovací tabulku se často používá funkce, která má velkou doménu. Pro vytvoření indexu z výstupu funkce lze použít modulo, které zmenší velikost domény tak, aby odpovídala velikosti pole; na mnoha procesorech je však často rychlejší omezit velikost hašovací tabulky na mocniny dvou velikostí a místo toho použít bitovou masku.
Příklad modulo i maskování v jazyce 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;}
.