En informática , una máscara o máscara de bits es un dato que se utiliza para operaciones a nivel de bit , en particular en un campo de bits . Mediante una máscara, se pueden activar o desactivar varios bits de un byte , nibble , palabra , etc., o invertirlos de activados a desactivados (o viceversa) en una única operación a nivel de bit. Un uso adicional del enmascaramiento implica la predicción en el procesamiento de vectores , donde la máscara de bits se utiliza para seleccionar qué operaciones de elementos del vector se van a ejecutar (el bit de máscara está habilitado) y cuáles no (el bit de máscara está despejado).
Para activar ciertos bits, se puede utilizar la operación bit a bit , siguiendo OR
el principio de que para un bit individual Y , Y OR 1 = 1
y Y OR 0 = Y
. Por lo tanto, para asegurarse de que un bit esté activado, OR
se puede utilizar con un 1
. Para dejar un bit sin cambios, OR
se utiliza con un 0
.
Ejemplo: enmascarar el nibble superior (bits 4, 5, 6, 7) mientras se deja el nibble inferior (bits 0, 1, 2, 3) sin cambios.
1001 0101 1010 0101 O 1111 0000 1111 0000 = 1111 0101 1111 0101
En la práctica, es más frecuente que los bits se "enmascaren " (o se enmascaren para 0
) que que se "enmascaren " (o se enmascaren para 1
). Cuando se AND
aplica un 0 a un bit, el resultado siempre es 0, es decir, Y AND 0 = 0
. Para dejar los demás bits como estaban originalmente, se pueden aplicar AND
con1
Y AND 1 = Y
Ejemplo: enmascarar el nibble superior ( bits 4, 5, 6, 7) mientras se deja el nibble inferior (bits 0, 1, 2, 3) sin cambios.
1001 0101 1010 0101Y 0000 1111 0000 1111 = 0000 0101 0000 0101
Es posible utilizar máscaras de bits para comprobar fácilmente el estado de bits individuales independientemente de los demás bits. Para ello, se desactivan todos los demás bits mediante el bitwise, AND
como se explicó anteriormente, y el valor se compara con 0
. Si es igual a 0
, entonces el bit estaba desactivado, pero si el valor es cualquier otro valor, entonces el bit estaba activado. Lo que hace que esto sea conveniente es que no es necesario averiguar cuál es realmente el valor, solo que no es 0
.
Ejemplo: Consulta del estado del 4º bit
1001 1 101 1001 0 101Y 0000 1 000 0000 1 000 = 0000 1 000 0000 0 000
Hasta ahora, el artículo ha explicado cómo activar y desactivar bits, pero no ambos a la vez. A veces, en realidad no importa cuál sea el valor, pero debe hacerse lo opuesto de lo que es actualmente. Esto se puede lograr utilizando la operación XOR
(o exclusiva) . XOR
devuelve 1
si y solo si un número impar de bits son 1
. Por lo tanto, si dos bits correspondientes son 1
, el resultado será un 0
, pero si solo uno de ellos es 1
, el resultado será 1
. Por lo tanto, la inversión de los valores de los bits se realiza invirtiéndolos XOR
con un 1
. Si el bit original era 1
, devuelve 1 XOR 1 = 0
. Si el bit original era , 0
devuelve 0 XOR 1 = 1
. Tenga en cuenta también que XOR
el enmascaramiento es seguro para los bits, lo que significa que no afectará a los bits no enmascarados porque Y XOR 0 = Y
, al igual que un OR
.
Ejemplo: alternar valores de bits
10011101 10010101O 00001111 11111111 = 10010010 01101010
Para escribir 1 y 0 arbitrarios en un subconjunto de bits, primero escriba 0 en ese subconjunto y luego configure los bits altos:
registro = (registro & ~máscara de bits) | valor;
En lenguajes de programación como C , los campos de bits son una forma útil de pasar un conjunto de argumentos booleanos nombrados a una función. Por ejemplo, en la API de gráficos OpenGL , hay un comando glClear()
que borra la pantalla u otros búferes. Puede borrar hasta cuatro búferes (los búferes de color, profundidad, acumulación y esténcil ), por lo que los autores de la API podrían haberlo hecho tomar cuatro argumentos. Pero entonces una llamada a él se vería así:
glClear ( 1 , 1 , 0 , 0 ); // Así no es como funciona realmente glClear y generaría un código inestable.
lo cual no es muy descriptivo. En su lugar, hay cuatro bits de campo definidos, GL_COLOR_BUFFER_BIT
, GL_DEPTH_BUFFER_BIT
, GL_ACCUM_BUFFER_BIT
y GL_STENCIL_BUFFER_BIT
y glClear()
se declara como
void glClear ( bits de GLbitfield );
Entonces una llamada a la función se ve así
glClear ( GL_COLOR_BUFFER_BIT | GL_PROFUNDIDAD_BUFFER_BIT );
Internamente, una función que toma un campo de bits como este puede usar binario and
para extraer los bits individuales. Por ejemplo, una implementación de glClear()
podría verse así:
void glClear ( GLbitfield bits ) { if (( bits & GL_COLOR_BUFFER_BIT ) != 0 ) { // Limpiar el búfer de color. } if (( bits & GL_DEPTH_BUFFER_BIT ) != 0 ) { // Limpiar el búfer de profundidad. } if (( bits & GL_ACCUM_BUFFER_BIT ) != 0 ) { // Limpiar el búfer de acumulación. } if (( bits & GL_STENCIL_BUFFER_BIT ) != 0 ) { // Limpiar el búfer de esténcil. } }
La ventaja de este enfoque es que se reduce la sobrecarga de argumentos de función. Dado que el tamaño mínimo de los datos es un byte, separar las opciones en argumentos separados sería desperdiciar siete bits por argumento y ocuparía más espacio en la pila. En cambio, las funciones normalmente aceptan uno o más enteros de 32 bits, con hasta 32 bits de opción en cada uno. Si bien es elegante, en la implementación más simple esta solución no es segura para los tipos . A GLbitfield
simplemente se define como un unsigned int
, por lo que el compilador permitiría una llamada sin sentido a glClear(42)
o incluso a glClear(GL_POINTS)
. En C++, una alternativa sería crear una clase para encapsular el conjunto de argumentos que glClear podría aceptar y podría encapsularse limpiamente en una biblioteca.
Las máscaras se utilizan con direcciones IP en las ACL (listas de control de acceso) de IP para especificar qué se debe permitir y denegar. Para configurar direcciones IP en interfaces, las máscaras comienzan con 255 y tienen los valores grandes en el lado izquierdo: por ejemplo, la dirección IP 203.0.113.129 con una máscara 255.255.255.224 . Las máscaras para las ACL de IP son al revés: por ejemplo, la máscara 0.0.0.255 . A esto a veces se le llama máscara inversa o máscara comodín . Cuando el valor de la máscara se descompone en binario (0 y 1), los resultados determinan qué bits de dirección se deben considerar al procesar el tráfico. Un bit 0 indica que se debe considerar el bit de dirección (coincidencia exacta); un bit 1 en la máscara es un "no importa". Esta tabla explica más a fondo el concepto.
Ejemplo de máscara:
Dirección de red (tráfico que se va a procesar): 192.0.2.0
máscara: 0.0.0.255
dirección de red (binaria): 11000000.00000000.00000010.00000000
máscara (binaria): 00000000.00000000.00000000.111111111
En base a la máscara binaria, se puede ver que los primeros tres conjuntos ( octetos ) deben coincidir exactamente con la dirección de red binaria dada (11000000.00000000.00000010). El último conjunto de números está formado por "no importa" (.11111111). Por lo tanto, todo el tráfico que comienza con " 192.0.2. " coincide, ya que el último octeto es "no importa". Por lo tanto, con esta máscara, se procesan las direcciones de red 192.0.2.1 a 192.0.2.255 ( 192.0.2.x ).
Reste la máscara normal de 255.255.255.255 para determinar la máscara inversa de ACL. En este ejemplo, la máscara inversa se determina para la dirección de red 198.51.100.0 con una máscara normal de 255.255.255.0 .
255.255.255.255 - 255.255.255.0 (máscara normal) = 0.0.0.255 (máscara inversa)
Equivalentes de ACL
El comodín source/source de 0.0.0.0 / 255.255.255.255 significa "cualquiera".
La fuente/comodín de 198.51.100.2 / 0.0.0.0 es el mismo que "host 198.51.100.2 "
En gráficos de computadora , cuando se pretende colocar una imagen dada sobre un fondo, las áreas transparentes se pueden especificar a través de una máscara binaria. [1] De esta manera, para cada imagen deseada hay en realidad dos mapas de bits : la imagen real, en la que las áreas no utilizadas reciben un valor de píxel con todos los bits establecidos en 0, y una máscara adicional , en la que las áreas de imagen correspondientes reciben un valor de píxel con todos los bits establecidos en 0 y las áreas circundantes un valor de todos los bits establecidos en 1. En la muestra de la derecha, los píxeles negros tienen los bits todos cero y los píxeles blancos tienen los bits todos uno.
En tiempo de ejecución , para colocar la imagen en la pantalla sobre el fondo, el programa primero enmascara los bits de los píxeles de la pantalla con la máscara de imagen en las coordenadas deseadas utilizando la operación AND bit a bit . Esto conserva los píxeles de fondo de las áreas transparentes mientras que restablece con ceros los bits de los píxeles que serán oscurecidos por la imagen superpuesta.
A continuación, el programa renderiza los bits de los píxeles de la imagen combinándolos con los bits de los píxeles del fondo mediante la operación OR bit a bit . De esta manera, los píxeles de la imagen se colocan de forma adecuada, pero se conservan los píxeles del fondo que los rodean. El resultado es una composición perfecta de la imagen sobre el fondo.
Esta técnica se utiliza para pintar cursores de dispositivos señaladores, en videojuegos 2D típicos para personajes, balas, etc. (los sprites ), para iconos de GUI y para títulos de videos y otras aplicaciones de mezcla de imágenes. Un método más rápido es simplemente sobrescribir los píxeles de fondo con los píxeles de primer plano si su alfa = 1
Aunque están relacionados (debido a que se utilizan para los mismos fines), los colores transparentes y los canales alfa son técnicas que no implican la mezcla de píxeles de la imagen mediante enmascaramiento binario.
Para crear una función hash para una tabla hash , a menudo se utiliza una función que tiene un dominio grande. Para crear un índice a partir de la salida de la función, se puede tomar un módulo para reducir el tamaño del dominio para que coincida con el tamaño de la matriz; sin embargo, a menudo es más rápido en muchos procesadores restringir el tamaño de la tabla hash a potencias de dos tamaños y usar una máscara de bits en su lugar.
Un ejemplo de módulo y enmascaramiento en C:
#include <stdint.h> #include <cadena.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 ; // Manejar la asignación de memoria para token_array… char token [] = "algún valor hashable" ; uint32_t hash_token = hash_function ( token , strlen ( token ), NUM_BUCKETS ); // Usando el módulo size_t index = hashed_token % MAX_RECORDS ; // O // Usando el tamaño de máscara de bits_t índice = hashed_token & HASH_BITMASK ; * ( matriz_token + índice ) = token ; // Libera la memoria de token_array … devuelve 0 ; }