¿Cómo funcionan las banderas en C?

2 minutos de lectura

Avatar de usuario de Justin Meiners
justin meiners

Recientemente me he encontrado con varios ejemplos de “banderas” en C y C++, y no entiendo muy bien cómo funcionan. Después de mirar un poco de código fuente, noté que a menudo los valores de las banderas se definen en hexadecimal, como los siguientes:

FLAG1 = 0x00000001,
FLAG2 = 0x00000010,

Mi intuición sugiere que estos valores se están combinando. ¿Funcionan las banderas combinando todos los valores de las banderas en un int? Si hubiera usado ambos como FLAG1 | FLAG2 seria el resultado 0x00000011?

¿Necesito crear enumeraciones con compensaciones de bits o puedo usar números enteros ascendentes como:

FLAG1 = 1;
FLAG2 = 2;

Debe compensar los bits; de lo contrario, no hay forma de extraer las banderas individuales. Si tuviera banderas correspondientes a 1, 2, 3 y 4, y un valor combinado de 5, ¿cómo podría saber si era 2 y 3 o 1 y 4?

También puedes hacerlo de esta manera, por ejemplo:

enum {
    FIRST = 1 << 0, // same as 1
    SECOND = 1 << 1, // same as 2, binary 10
    THIRD = 1 << 2, // same as 4, binary 100
    FOURTH = 1 << 3 // same as 8, binary 1000
};

Luego combinas banderas así:

int flags = FIRST | THIRD | FOURTH;

Y los extraes así:

if (flags & THIRD) { ...

Avatar de usuario de Mark Byers
marca byers

Su primer método no es usar los bits de la manera más eficiente. En el primer ejemplo, está utilizando notación hexadecimal y es equivalente a:

TEXTUREFLAGS_POINTSAMPLE = 1,
TEXTUREFLAGS_TRILINEAR = 16,

En el segundo método, parece que solo está aumentando en uno cada vez. Esto no funcionará cuando combine banderas, porque el valor combinado podría ser el mismo que otra bandera (por ejemplo, 1 | 2 == 3).

Deberías usar estos valores en su lugar:

0x00000001  // == 1
0x00000002  // == 2
0x00000004  // == 4
0x00000008  // == 8
0x00000010  // == 16
0x00000020  // == 32
0x00000040  // == 64
etc...

Estas son las potencias de dos y se pueden combinar usando bit a bit o de cualquier forma sin dar colisiones.

  • Ok, pero no funcionará si solo hago uno para dar me gusta a 20, ¿verdad? Todavía tengo que escalonar el hexadecimal para que no se sobrescriban, ¿verdad? O no entiendo cómo funciona.

    –Justin Meiners

    4 sep 2010 a las 19:30

  • @ user425756, si no usa potencias de dos, no puede notar la diferencia entre el 1 y el 2 configurados, o el 3 configurado.

    –Paul Tomblin

    4 sep 2010 a las 19:33

  • Sí, eso es lo que estaba pensando.

    –Justin Meiners

    4 sep 2010 a las 19:39

Indicadores como este son valores binarios, por lo que puede combinar 1, 2, 4, 8, 16, 32, 64, 128 en un solo byte, o más potencias de 2 hasta 2^31 en un int. Debido a que son valores binarios, puedes “o” juntos, así que si “o” juntos 1,2,4 terminas con 7, por ejemplo. Y puede extraer el bit que desea usando “y”, por lo que si tiene un int con algunas banderas o juntas, y desea ver si el bit “4” está configurado, puede decir if (flag & 4) y será cierto si se establece el bit “4”.

  • Gracias eso tiene más sentido.

    –Justin Meiners

    4 sep 2010 a las 19:33

Piense en las banderas como una matriz de 32 bits (booleanos)

Para activar uno de estos bits en usted O con 1

Una vez que supere la diferencia entre OR/AND digital y OR/AND lógico, todo encajará. ¡Entonces apreciarás la notación hexadecimal!

¿Ha sido útil esta solución?