What operation is used to identify that value 5 represent TYPE_1 with
TYPE_3?
Suppongo che tu voglia dire che ti è stato dato un value
(ad esempio 5
) e vuoi sapere come dire che il primo e il terzo bit sono impostati e quindi rappresentano TYPE_1
e TYPE_3
.
Ci sono un paio di modi per gestirlo. Entrambi prevedono l'uso di una serie di AND logici per escludere tutti i bit nel valore che hai ricevuto tranne quello che ti interessa per vedere se il bit rimanente è 1
o 0
:
00000101 The value; 5 in this case
and 00000100 The mask, TYPE_3
--------
00000100 The ANDed result, which is nonzero. TYPE_3's bit is set.
Stessa cosa, ma con TYPE_2
, che non è presente in value
:
00000101 The value; 5 in this case
and 00000010 The mask, TYPE_2
--------
00000000 The ANDed result, which is zero. TYPE_2's bit is not set.
Il primo modo per gestirlo è fare confronti su ogni tipo:
if ( value & TYPE_1 ) handle_type_1();
if ( value & TYPE_2 ) handle_type_2();
...etc...
Questo è il metodo forza bruta, ma se sei dipendente dalle macro TYPE_*
definite in qualche file di intestazione, questo è l'unico modo per farlo in sicurezza. Non puoi dipendere dai bit che rappresentano ogni tipo che non cambia. (E vergogna su chi ha scritto il file di intestazione per non aver fornito alcune funzioni o macro per aiutarti a capire queste cose.)
Se do ha il controllo sulla disposizione del campo di bit e può dichiarare che bit n
rappresenta il tipo n
, diventa facile mettere insieme alcune macro (o funzioni se non usare C) per gestirlo:
#define NUMBER_OF_TYPES 4
/* These are bit numbers, not powers of two */
#define TYPE_1 1
#define TYPE_2 2
#define TYPE_3 3
#define TYPE_4 4
#define TYPE_MASK(t) (1 << (t-1))
#define VALUE_HAS_TYPE(v,t) ((v) & TYPE_MASK((t)))
/* Construct a value holding two types */
unsigned value = TYPE_MASK(TYPE_1) | TYPE_MASK(TYPE_3);
for (unsigned type_num=0 ; type_num < NUMBER_OF_TYPES ; ++type_num) {
if ( VALUE_HAS_TYPE(value, type_num)
do_something_with_type_number(type_num);
}
Questo itera il numero di tipi che hai, controlla se ognuno è presente e poi chiama una funzione con il suo numero di tipo. Questo ti dà un'enorme flessibilità in do_something_with_type_number()
, perché puoi usare un'istruzione switch
sul numero del tipo o usarla come indice in una matrice che potrebbe puntare a funzioni per gestire ciascun tipo. Non puoi fare nessuna di quelle con confronti bit a bit.