2011-10-20 18 views
6

Forse la domanda è così semplice ...sul enum e bit per bit operazione

C'è una definizione di enum:

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

Da qualche parte nel codice c'è:

if (uop->flags & FCTRL) 

Quando questo condizione è vera e quando non lo è?

risposta

14

In definitiva, questo codice controlla se un bit singolo (il flag FCTRL) è attivato nella variabile uop->flags.

ma ecco qualche spiegazione:

Implicitamente, il codice if(X) controlli per X è un valore "vero". Per gli interi, 0 è l'unico valore "falso" e tutto il resto è "vero".

Pertanto il codice è equivalente a:

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

Ora, che cosa significa?

L'operatore & esegue un "AND bit a bit", che significa che ogni bit del lato sinistro è ANDed con il bit corrispondente sul lato destro.

Quindi, se abbiamo scritto le nostre due operandi in binario:

uop->flags  1010 1010 (example) 

FCTRL   0100 0000 

In questo esempio, se si esegue un "AND" su ogni coppia di bit, si ottiene il risultato:

result   0000 0000 

Che viene valutato come falso, e in effetti in quell'esempio il valore uop->flags non ha il flag FCTRL impostato.

Ora ecco un altro esempio, dove la bandiera è insieme:

uop->flags  1110 1010 (example) 

FCTRL   0100 0000 

Il risultato AND corrispondente:

result   0100 0000 

Questo risultato è diverso da zero, quindi, "vero", innescando la tua if dichiarazione.

1

Quando il bit corrispondente a FCTRL (0x040) è impostato in uop-> flags, la condizione è vera. '&' è un bit AND che in effetti maschera tutti i bit tranne quelli impostati da FCTRL.

+0

uop-> flags = 0x140 => la condizione è vera? – mahmood

+0

sì perché il risultato di 0x140 e 0x040 è 0x040. – Lou

+0

Vedere http://en.wikipedia.org/wiki/Bitwise_operation per ulteriori dettagli sulle operazioni bit a bit. – Lou

5

Questo è un enum utilizzato per definire un numero di "flag" per un'operazione. Si può dedurre dal fatto che ogni valore definito è una potenza esatta di due, e per questo è rappresentato da un singolo bit ("flag") di un valore.

Il vantaggio di questo tipo di enum è che è possibile combinare il maggior numero di bandiere come si desidera utilizzando bitwise OR:

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

La condizione si dà, che utilizza bitwise AND

uop->flags & FCTRL 

è vero se e solo se è impostato il flag FCTRL, cioè quando è impostato il 7 ° bit di uop->flags. Questo perché FCTRL == 0x040 == binario 01000000.

+0

Cosa devo fare se voglio verificare se FRET è impostato? – mahmood

+0

@mahmood: 'if (uop-> flags & FRET) {/ * FRET è impostato * /}' – Jon

0

La condizione è vera quando il bit è impostato. 0x40 è 1000000, quindi quando è settato il 7 ° bit in flags, sarà vero.

0

Poiché il tipo di enumerazione utilizza la posizione delle cifre binarie (cioè unità, 2, 4, 8, 16 ecc.) E l'operazione esegue una logica e. Se quel bit è impostato, il valore non sarà zero (true) altrimenti sarà falso.

0

In questo caso, ogni elemento enumerazione successivo viene spostato di 1 bit a sinistra, quindi è legale verificare se è impostato un flag semplicemente controllando se variable & flag == true. Tuttavia, cosa succede se si desidera impostare il modello di flag multi-bit? Ad esempio:

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

quando verificare se la nostra variabile X ha questo flag impostato? Non possiamo semplicemente fare X & myFlag == true, perché ad esempio 0b1000 & myFlag == true e 0b0010 & myFlag == true - ma né 0b1000 né 0b0010 ha i nostri DUE bit impostati! Per questo motivo preferisco pieno controllo della maschera di bit che permette di definire i modelli multi-bit in enum:

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

hth!