¿Cómo puedo usar una máscara de bits?

6 minutos de lectura

avatar de usuario
animea animea

¿Cómo lo uso en C++? ¿Cuándo es útil usarlo?

¿Cuál sería un ejemplo de un problema en el que se usa una máscara de bits para ver cómo funciona realmente?

  • tienes c++11? y std::conjunto de bits?

    – dzada

    3 de septiembre de 2013 a las 12:05

  • std::ios_base::fmtflags.

    – James Kanze

    3 de septiembre de 2013 a las 12:06

  • google.com/search?q=qué+es+una+máscara de bits

    – LarryPel

    3 de septiembre de 2013 a las 12:06

  • Posible duplicado de google.

    – Marún

    3 de septiembre de 2013 a las 12:07

  • Relacionado, pero no duplicado: C/C++ verifica si un bit está configurado, es decir, variable int. De todos modos, la máscara de bits se usa en C, no en C++ donde std::bitset debe ser preferido.

    – Mouviciel

    3 de septiembre de 2013 a las 12:09

avatar de usuario
goGud

Brevemente, una máscara de bits ayuda a manipular la posición de múltiples valores. Hay un buen ejemplo aquí;

Bitflags son un método para almacenar múltiples valores, que no son mutuamente excluyentes, en una variable. Probablemente los hayas visto antes. Cada indicador es una posición de bit que se puede activar o desactivar. Luego tiene un montón de máscaras de bits #definidas para cada posición de bit para que pueda manipularlas fácilmente:

    #define LOG_ERRORS            1  // 2^0, bit 0
    #define LOG_WARNINGS          2  // 2^1, bit 1
    #define LOG_NOTICES           4  // 2^2, bit 2
    #define LOG_INCOMING          8  // 2^3, bit 3
    #define LOG_OUTGOING         16  // 2^4, bit 4
    #define LOG_LOOPBACK         32  // and so on...

// Only 6 flags/bits used, so a char is fine
unsigned char flags;

// Initialising the flags,
// Note that assigning a value will clobber any other flags, so you
// it should generally only use the = operator when initialising variables.
flags = LOG_ERRORS;
// Sets to 1 i.e. bit 0

// Initialising to multiple values with OR (|)
flags = LOG_ERRORS | LOG_WARNINGS | LOG_INCOMING;
// sets to 1 + 2 + 8 i.e. bits 0, 1 and 3

// Setting one flag on, leaving the rest untouched
// OR bitmask with the current value
flags |= LOG_INCOMING;

// Testing for a flag
// AND with the bitmask before testing with ==
if ((flags & LOG_WARNINGS) == LOG_WARNINGS)
   ...

// Testing for multiple flags
// As above, OR the bitmasks
if ((flags & (LOG_INCOMING | LOG_OUTGOING))
         == (LOG_INCOMING | LOG_OUTGOING))
   ...

// Removing a flag, leaving the rest untouched
// AND with the inverse (NOT) of the bitmask
flags &= ~LOG_OUTGOING;

// Toggling a flag, leaving the rest untouched
flags ^= LOG_LOOPBACK;

**

ADVERTENCIA: NO use el operador de igualdad (es decir, banderas de bits == máscara de bits) para probar si una bandera está configurada; esa expresión solo será verdadera si esa bandera está configurada y todas las demás no están configuradas. Para probar una sola bandera, debe usar & y ==:

**

if (flags == LOG_WARNINGS) //DON'T DO THIS
   ...
if ((flags & LOG_WARNINGS) == LOG_WARNINGS) // The right way
   ...
if ((flags & (LOG_INCOMING | LOG_OUTGOING)) // Test for multiple flags set
         == (LOG_INCOMING | LOG_OUTGOING))
   ...

También puedes buscar Trucos de C++.

  • en su ejemplo sobre bitflags, ¿cómo sabe qué bit pertenece a qué variable? ¿su posición en el byte, o el valor real del byte activa y desactiva ciertas funciones?

    – MarcusJ

    1 de junio de 2015 a las 19:38

  • “Bitflags son un método de almacenamiento…”, etc. y todo el primer bloque de código se copia directamente de la fuente sin ninguna indicación clara de que no son las propias palabras del usuario “goGud”. ¿De dónde está plagiada la última parte?

    -Peter Mortensen

    26 de agosto a las 2:35


El enmascaramiento de bits es “útil” para usar cuando desea almacenar (y luego extraer) diferentes datos dentro de un solo valor de datos.

Una aplicación de ejemplo que he usado antes es imaginar que estuviera almacenando valores de color RGB en un valor de 16 bits. Así que algo que se parece a esto:

RRRR RGGG GGGB BBBB

A continuación, podría utilizar el enmascaramiento de bits para recuperar los componentes de color de la siguiente manera:

  const unsigned short redMask   = 0xF800;
  const unsigned short greenMask = 0x07E0;
  const unsigned short blueMask  = 0x001F;

  unsigned short lightGray = 0x7BEF;

  unsigned short redComponent   = (lightGray & redMask) >> 11;
  unsigned short greenComponent = (lightGray & greenMask) >> 5;
  unsigned short blueComponent =  (lightGray & blueMask);

  • No entiendo esto, ¿está diciendo que 0xF800 es básicamente un grupo de bits del que está seleccionando (es decir, está extrayendo esos bits de un grupo establecido de bytes por dirección)? Pensé que una máscara de bits era básicamente un int del mismo tamaño que los datos (por lo que en este caso serían 48 bits) y la máscara se aplicó por encima, cuando los valores de la máscara son 1, se muestra el valor del bit subyacente, y cuando es cero, no lo hace, lo que le permite ignorar los bits de apagado? y para que sirve el cambio?

    – MarcusJ

    1 jun 2015 a las 19:36

  • @MarcusJ: consulte el ejemplo de goGud a continuación, que proporciona más detalles sobre las máscaras de bits (es decir, stackoverflow.com/questions/18591924/how-to-use-bitmask/…)

    – a505999

    16 de febrero de 2016 a las 18:41


  • Soy un idiota. Sabía qué era el enmascaramiento de bits, pero no me di cuenta de que el triple RGB no era de 8 bits cada uno, lo que me confundió. gracias por la ayuda! 🙂

    – MarcusJ

    17 de febrero de 2016 a las 8:36

  • @MarcusJ: RGB triple puede ser de 8 bits para cada canal y normalmente lo es. Sin embargo, hay algunos formatos RGB en los que los canales pueden tener menos de 8 bits, como 5, 6, 5, de modo que RGB se puede ajustar a 16 bits.

    – Damián Dixon

    21 de agosto de 2017 a las 5:46

  • @PeterMortensen No puede ser simétrico. Hay 16 bits disponibles y 3 tipos de datos (RGB). 16/3 = 5 bits para cada uno + 1 bit adicional. Esto se asigna a G en formato RGB16. Ver stackoverflow.com/a/9958424 y su enlace multimedia.cx/mmbasics.txt [specifically the section about RGB and YUV colorspaces]

    – El maestro

    4 sep a las 19:55


Digamos que tengo un valor ARGB de 32 bits con 8 bits por canal. Quiero reemplazar el componente alfa con otro valor alfa, como 0x45

unsigned long alpha = 0x45
unsigned long pixel = 0x12345678;
pixel = ((pixel & 0x00FFFFFF) | (alpha << 24));

La máscara convierte los 8 bits superiores a 0, donde estaba el antiguo valor alfa. El valor alfa se desplaza hacia arriba hasta las posiciones de bits finales que tomará, luego se aplica OR en el valor de píxel enmascarado. El resultado final es 0x45345678 que se almacena en píxeles.

Las máscaras de bits se utilizan cuando desea codificar varias capas de información en un solo número.

Entonces (suponiendo permisos de archivo Unix) si desea almacenar 3 niveles de restricción de acceso (lectura, escritura, ejecución), puede verificar cada nivel al verificar el bit correspondiente.

rwx
---
110

110 en base 2 se traduce a 6 en base 10.

Por lo tanto, puede verificar fácilmente si alguien puede, por ejemplo, leer el archivo haciendo clic en el campo de permiso con el permiso deseado.

Pseudocódigo:

PERM_READ = 4
PERM_WRITE = 2
PERM_EXEC = 1

user_permissions = 6

if ((user_permissions & PERM_READ) == PERM_READ) then
  // this will be reached, as 6 & 4 is true
fi

Necesita una comprensión práctica de la representación binaria de números y operadores lógicos para comprender los campos de bits.

¿Ha sido útil esta solución?