Mask (computing)
Funktioiden argumentitEdit
Ohjelmointikielissä, kuten C:ssä, bittikentät ovat käyttökelpoinen tapa välittää joukko nimettyjä boolean-argumentteja funktiolle. Esimerkiksi grafiikka API OpenGL:ssä on komento glClear()
, joka tyhjentää näytön tai muita puskureita. Se voi tyhjentää enintään neljä puskuria (väri-, syvyys-, kertymä- ja sabluunapuskurit), joten API:n laatijat olisivat voineet antaa sille neljä argumenttia. Mutta silloin kutsu sille näyttäisi seuraavalta
glClear(1,1,0,0); // This is not how glClear actually works and would make for unstable code.
, mikä ei ole kovin kuvaavaa. Sen sijaan on neljä määriteltyä kentän bittiä, GL_COLOR_BUFFER_BIT
, GL_DEPTH_BUFFER_BIT
, GL_ACCUM_BUFFER_BIT
ja GL_STENCIL_BUFFER_BIT
, ja glClear()
ilmoitetaan muodossa
void glClear(GLbitfield bits);
Tällöin kutsu funktiolle näyttää tältä
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Kansallisesti funktio, joka ottaa tällaisen bittikentän, voi käyttää binääritiedostoa and
purkaakseen yksittäiset bitit. Esimerkiksi glClear()
:n toteutus voisi näyttää seuraavalta:
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. }}
Tämän lähestymistavan etuna on, että funktion argumenttien yleiskäyttö vähenee. Koska datan minimikoko on yksi tavu, vaihtoehtojen erottaminen erillisiksi argumenteiksi tuhlaisi seitsemän bittiä per argumentti ja veisi enemmän pinotilaa. Sen sijaan funktiot hyväksyvät yleensä yhden tai useamman 32-bittisen kokonaisluvun, joissa kussakin on enintään 32 optiobittiä. Vaikka tämä ratkaisu on tyylikäs, yksinkertaisimmassa toteutuksessa se ei ole tyyppiturvallinen. GLbitfield
määritellään yksinkertaisesti unsigned int
:ksi, joten kääntäjä sallisi merkityksettömän kutsun glClear(42)
:lle tai jopa glClear(GL_POINTS)
:lle. C++:ssa vaihtoehtona olisi luoda luokka, joka kapseloisi joukon argumentteja, jotka glClear voisi hyväksyä ja jotka voitaisiin puhtaasti kapseloida kirjastoon.
Inverse masksEdit
Maskeja käytetään IP-osoitteiden kanssa IP ACL:ssä (Access Control Lists) määrittelemään, mitä pitäisi sallia ja mitä kieltää. Rajapintojen IP-osoitteiden määrityksessä maskit alkavat kirjaimella 255 ja niiden vasemmalla puolella on suuret arvot: esimerkiksi IP-osoite 209.165.202.129, jonka maski on 255.255.255.255.224. IP ACL:ien maskit ovat päinvastaisia: esimerkiksi maski 0.0.0.0.255. Tätä kutsutaan joskus käänteiseksi maskiksi tai jokerimaskiksi. Kun maskin arvo jaetaan binäärimerkkeihin (0:t ja 1:t), tulokset määrittävät, mitkä osoitteen bitit otetaan huomioon liikennettä käsiteltäessä. 0 tarkoittaa, että osoitebitit on otettava huomioon (tarkka vastaavuus); 1 maskissa on ”ei kiinnosta”. Tämä taulukko selittää käsitettä tarkemmin.
Mask esimerkki:
verkon osoite (käsiteltävä liikenne) 10.1.1.0
mask0.0.0.255
verkon osoite (binääri)00001010.00000001.00000001.00000000
mask (binäärinen)00000000.00000000.00000000.11111111
Binäärisen maskin perusteella voidaan nähdä, että kolmen ensimmäisen sarjan (oktetin) on täsmälleen vastattava annettua binääristä verkko-osoitetta (00001010.00000001.00000001). Viimeinen numerosarja koostuu ”ei kiinnosta” (.1111111111). Näin ollen kaikki liikenne, joka alkaa kirjaimella 10.1.1., täsmää, koska viimeinen oktetti on ”don’t care”. Tällä maskilla käsitellään siis verkko-osoitteita 10.1.1.1-10.1.1.255 (10.1.1.1.x).
Miinusta normaali maski 255.255.255.255.255:stä ACL:n käänteismaskin määrittämiseksi. Tässä esimerkissä käänteinen maski määritetään verkko-osoitteelle 172.16.1.0, jonka normaali maski on 255.255.255.0.
255.255.255.255.255 – 255.255.255.255.0 (normaali maski) = 0.0.0.255 (käänteinen maski)
ACL-ekvivalentit
Lähde/lähde-wildcard 0.0.0.0/255.255.255.255.255.255 tarkoittaa ”mitä tahansa”.
Lähde/wildcard 10.1.1.2/0.0.0.0.0 on sama kuin ”isäntä 10.1.1.2”
Kuvan maskejaMuokkaa
Tietokonegrafiikassa, kun tietty kuva on tarkoitus sijoittaa taustan päälle, läpinäkyvät alueet voidaan määritellä binäärimaskilla. Näin kutakin aiottua kuvaa varten on itse asiassa kaksi bittikarttaa: varsinainen kuva, jossa käyttämättömille alueille annetaan pikselin arvo, jossa kaikki bitit on asetettu 0:ksi, ja ylimääräinen maski, jossa vastaaville kuva-alueille annetaan pikselin arvo, jossa kaikki bitit on asetettu 0:ksi, ja ympäröiville alueille arvo, jossa kaikki bitit on asetettu 1:ksi. Oikealla olevassa näytteessä mustilla pikseleillä on kaikki nollabitit ja valkoisilla pikseleillä kaikki ykkösbitit.
Ajoaikana, jotta kuva saataisiin kuvaruudulle taustan päälle, ohjelma maskeeraa ensin kuvaruudun pikselin bitit kuvamaskin kanssa halutuissa koordinaateissa käyttäen bittimäistä AND-operaatiota. Tämä säilyttää läpinäkyvien alueiden taustapikselit ja nollaa niiden pikselien bitit, jotka peittyvät päällekkäisen kuvan alle.
Sitten ohjelma renderöi kuvapikselin bitit yhdistämällä ne taustapikselin bitteihin bittiosoittaisella OR-operaatiolla. Näin kuvapikselit sijoitetaan sopivasti samalla kun taustaa ympäröivät pikselit säilyvät. Tuloksena on kuvan täydellinen yhdistelmä taustan päälle.
Tätä tekniikkaa käytetään osoitinlaitteiden kursoreiden maalaamiseen, tyypillisissä 2D-videopeleissä hahmojen, luotien ja niin edelleen (sprites), GUI-kuvakkeiden sekä videoiden otsikoinnissa ja muissa kuvien sekoitussovelluksissa.
Vaikka ne liittyvätkin toisiinsa (koska niitä käytetään samoihin tarkoituksiin), läpinäkyvät värit ja alfakanavat ovat tekniikoita, joihin ei liity kuvapikselien sekoittamista binäärisellä maskeerauksella.
Hash-taulukotMuokkaa
Hash-taulukon hash-funktion luomiseksi käytetään usein funktiota, jolla on suuri alue. Indeksin luomiseksi funktion ulostulosta voidaan ottaa modulo pienentämään toimialueen kokoa vastaamaan matriisin kokoa; monilla prosessoreilla on kuitenkin usein nopeampaa rajoittaa hash-taulukon koko kahden koon potensseihin ja käyttää sen sijaan bittimaskia.
Esimerkki sekä modulosta että maskeerauksesta C:ssä:
#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;}