2011-10-20 15 views
6

Tal vez la pregunta es tan simple ...en la enumeración y bit a bit operación

Hay una definición de enumeración:

enum uop_flags_enum { 
    FICOMP  = 0x001, 
    FLCOMP  = 0x002, 
    FFCOMP  = 0x004, 
    FMEM   = 0x008, 
    FLOAD   = 0x010, 
    FSTORE  = 0x020, 
    FCTRL   = 0x040, 
    FCALL   = 0x080, 
    FRET   = 0x100, 
    FCOND   = 0x200 
}; 

En alguna parte del código que hay:

if (uop->flags & FCTRL) 

Cuando esto la condición es verdadera y cuando no lo es?

Respuesta

14

En última instancia, este código está comprobando si un solo bit (el indicador FCTRL) está activado en la variable uop->flags.

Pero aquí es una explicación:

Implícitamente, el código if(X) cheques para x son un valor "verdadero". Para enteros, 0 es el único valor "falso" y todo lo demás es "verdadero".

lo tanto, su código es equivalente a:

if (0 != (uop->flags & FCTRL))

Ahora bien, ¿qué significa eso?

El operador & realiza una "Y a nivel de bit", lo que significa que cada bit del lado izquierdo se AND con el bit correspondiente en el lado derecho.

Así que si escribimos nuestros dos operandos en binario:

uop->flags  1010 1010 (example) 

FCTRL   0100 0000 

En este ejemplo, si realiza una "Y" en cada par de bits, se obtiene el resultado:

result   0000 0000 

que se evalúa como falso, y de hecho en ese ejemplo, el valor uop->flags no tiene el indicador FCTRL establecido.

Ahora aquí es otro ejemplo, donde la bandera es conjunto:

uop->flags  1110 1010 (example) 

FCTRL   0100 0000 

El resultado AND correspondiente:

result   0100 0000 

Este resultado no es cero, por lo tanto, "verdadero", lo que provocó su if declaración.

1

Cuando el bit correspondiente a FCTRL (0x040) se establece en uop-> flags, la condición es verdadera. '&' es un Y a nivel de bits que enmascara todos los bits excepto los establecidos por FCTRL.

+0

uop-> flags = 0x140 => ¿es verdadera la condición? – mahmood

+0

sí porque el resultado de 0x140 y 0x040 es 0x040. – Lou

+0

Consulte http://en.wikipedia.org/wiki/Bitwise_operation para obtener más detalles sobre las operaciones en modo bit. – Lou

5

Esta es una enumeración utilizada para definir un número de "banderas" para una operación. Puede deducir esto por el hecho de que cada valor definido es una potencia exacta de dos, y debido a esto se representa por un solo bit ("bandera") de un valor.

La ventaja de este tipo de enumeración es que se pueden combinar como muchas de las banderas como desee mediante el uso de bitwise OR:

uop->flags = FMEM | FLOAD | FRET; // sets the three corresponding flags 

La condición se da, que utiliza bitwise AND

uop->flags & FCTRL 

es verdadero si y solo si se establece el indicador FCTRL, es decir, cuando se establece el 7º bit de uop->flags. Esto es porque FCTRL == 0x040 == binario 01000000.

+0

¿Qué debo hacer si deseo verificar si FRET está configurado? – mahmood

+0

@mahmood: 'if (uop-> flags & FRET) {/ * FRET está configurado * /}' – Jon

0

La condición es verdadera cuando se establece el bit. 0x40 es 1000000, por lo que cuando se establece el 7mo bit en flags, será verdadero.

0

Como el tipo enumerate está haciendo uso de la posición de los dígitos binarios (es decir, unidades, 2, 4, 8, 16 etc.) y la operación hace una lógica y. Si ese lugar de bit está configurado, el valor no será cero (verdadero); de lo contrario, será falso.

0

En este caso, cada siguiente elemento enum se desplaza por 1 bit a la izquierda, por lo que es legal comprobar si se establece alguna marca simplemente marcando variable & flag == true. Sin embargo, ¿qué ocurre si queremos establecer un patrón de bandera de varios bits? Por ejemplo-

enum { 
    #ifdef __GNUC__ // cool in GCC we can use binary constants 
     myFlag = 0b1010 
    #else   // otherwise fallback into integral constant mode 
     myFlag = 10 
    #endif 
} 

cuando la forma de comprobar si la variable X ha establecido esta bandera? No podemos simplemente hacer X & myFlag == true, porque por ejemplo 0b1000 & myFlag == true y 0b0010 & myFlag == true - ¡pero ni 0b1000 ni 0b0010 tienen nuestros DOS bits establecidos! Por esta razón prefiero un chequeo total de máscara de bits que permite definir los patrones de bits múltiples en la enumeración:

#define IS_BIT_MASK_SET(variable,flag) ((variable & flag) == flag) 

hth!

Cuestiones relacionadas