¿Qué es el enmascaramiento de bits?

191

Soy bastante nuevo en la programación en C y encontré un poco de enmascaramiento. ¿Alguien puede explicarme el concepto general y la función del enmascaramiento de bits? Los ejemplos son muy apreciados.

Mr.Z
fuente
1
¿Entiendes operadores bit a bit como & | ^ etc y lógica booleana en general? Cualquier explicación de las operaciones de máscara requerirá esto.
Paul R
1
Sí, entiendo los operadores bit a bit y la lógica booleana
Mr.Z
2
Sé que los enlaces no deben publicarse, pero la explicación de Wikipedia es excelente: en.wikipedia.org/wiki/Mask_(computing)
pevik
2
@pevik está bien publicar un enlace, pero con alguna descripción, de modo que si el enlace desaparece algún día, la publicación aún puede cumplir su propósito de responder. Además, el enlace no debe ser con fines meramente promocionales.
Dexter

Respuestas:

246

Una máscara define qué bits desea conservar y qué bits desea eliminar.

El enmascaramiento es el acto de aplicar una máscara a un valor. Esto se logra haciendo:

  • Biting AND para extraer un subconjunto de los bits en el valor
  • Biting ORing para establecer un subconjunto de los bits en el valor
  • Bitwise XORing para alternar un subconjunto de los bits en el valor

A continuación se muestra un ejemplo de extracción de un subconjunto de los bits en el valor:

Mask:   00001111b
Value:  01010101b

Aplicar la máscara al valor significa que queremos borrar los primeros 4 bits (superiores) y mantener los últimos 4 bits (inferiores). Por lo tanto, hemos extraído los 4 bits inferiores. El resultado es:

Mask:   00001111b
Value:  01010101b
Result: 00000101b

El enmascaramiento se implementa usando AND, por lo que en C obtenemos:

uint8_t stuff(...) {
  uint8_t mask = 0x0f;   // 00001111b
  uint8_t value = 0x55;  // 01010101b
  return mask & value;
}

Aquí hay un caso de uso bastante común: extraer bytes individuales de una palabra más grande. Definimos los bits de orden superior en la palabra como el primer byte. Utilizamos dos operadores para esto &, y >>(desplazamiento a la derecha). Así es como podemos extraer los cuatro bytes de un entero de 32 bits:

void more_stuff(uint32_t value) {             // Example value: 0x01020304
    uint32_t byte1 = (value >> 24);           // 0x01020304 >> 24 is 0x01 so
                                              // no masking is necessary
    uint32_t byte2 = (value >> 16) & 0xff;    // 0x01020304 >> 16 is 0x0102 so
                                              // we must mask to get 0x02
    uint32_t byte3 = (value >> 8)  & 0xff;    // 0x01020304 >> 8 is 0x010203 so
                                              // we must mask to get 0x03
    uint32_t byte4 = value & 0xff;            // here we only mask, no shifting
                                              // is necessary
    ...
}

Tenga en cuenta que puede cambiar el orden de los operadores anteriores, primero puede hacer la máscara, luego el cambio. Los resultados son los mismos, pero ahora tendría que usar una máscara diferente:

uint32_t byte3 = (value & 0xff00) >> 8;
usuario239558
fuente
55
Buena respuesta, pero también se puede aplicar el enmascaramiento para configurar o alternar bits específicos con operaciones OR o XOR y una máscara adecuada.
Paul R
@ user239558 gracias por el ejemplo y la sintaxis adecuada. @ Paul R. ¿Diría simplemente máscara Y valor en el ejemplo proporcionado por user239558
Mr.Z
@ Mr.Z: en C, C ++ y lenguajes relacionados, sería el operador AND bit a bit , que se escribe como &.
Paul R
@ Mr.Z Por ejemplo: un byte clara de un uint32_t enmascarando los contenidos de distancia: #define MASK 0x000000FF .... my_uint32_t &= ~MASK.
Lundin,
el bpara indicar el literal binario no es compatible con todos los compiladores, ¿correcto?
Ungeheuer
76

Enmascarar significa mantener / cambiar / eliminar una parte deseada de la información. Veamos una operación de enmascaramiento de imágenes; como esta operación de enmascaramiento está eliminando cualquier cosa que no sea piel

ingrese la descripción de la imagen aquí

Estamos haciendo Y operación en este ejemplo. También hay otros operadores de enmascaramiento: OR , XOR .


Bit-Masking significa imponer una máscara sobre bits. Aquí hay un enmascaramiento de bits con AND -

     1 1 1 0 1 1 0 1   [input]
(&)  0 0 1 1 1 1 0 0    [mask]
------------------------------
     0 0 1 0 1 1 0 0  [output]

Por lo tanto, solo quedan los 4 bits centrales (ya que estos bits están 1en esta máscara).

Veamos esto con XOR -

     1 1 1 0 1 1 0 1   [input]
(^)  0 0 1 1 1 1 0 0    [mask]
------------------------------
     1 1 0 1 0 0 0 1  [output]

Ahora, los 4 bits centrales se voltean (se 1convirtieron 0, se 0convirtieron 1).


Entonces, usando bit-mask podemos acceder a bits individuales [ ejemplos ]. A veces, esta técnica también se puede utilizar para mejorar el rendimiento. Toma esto por ejemplo

bool isOdd(int i) {
    return i%2;
}

Esta función indica si un número entero es impar / par. Podemos lograr el mismo resultado con más eficiencia usando bit-mask-

bool isOdd(int i) {
    return i&1;
}

Explicación breve : si el bit menos significativo de un número binario es 1entonces es impar; porque 0será parejo. Entonces, al hacer AND con 1, estamos eliminando todos los demás bits, excepto el bit menos significativo, es decir:

     55  ->  0 0 1 1 0 1 1 1   [input]
(&)   1  ->  0 0 0 0 0 0 0 1    [mask]
---------------------------------------
      1  <-  0 0 0 0 0 0 0 1  [output]
Minhas Kamal
fuente
1
Además, para convertir un número entero en un número impar. si es un número par: i = i | 1. Esto es útil cuando estamos tratando de generar una secuencia como 1, 3, 5, ..., 2, 4, 6, ...
Harshit Sharma
También puede usar la siguiente operación para encontrar el número con solo el bit menos significativo de un entero: lsb = i & -i
Harshit Sharma