Uso della potenza di 2 numeri per rappresentare i tipi

0

Diciamo che abbiamo alcuni valori, rappresentati dalla potenza di 2:

TYPE_1 = 1
TYPE_2 = 2
TYPE_3 = 4
TYPE_4 = 8
...

Ho bisogno di memorizzare alcuni di questi tipi in un unico valore.

Esempio: Per rappresentare TYPE_1 con TYPE_3 , il valore è 5 .

Quale operazione viene utilizzata per identificare quel valore 5 rappresenta TYPE_1 con TYPE_3 ?

    
posta Rodrigo 04.07.2013 - 18:16
fonte

3 risposte

5

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.

    
risposta data 04.07.2013 - 20:22
fonte
4

Se usi bitwise o operatore, otterrai il valore 5

print(TYPE_1 | TYPE_3) //5
    
risposta data 04.07.2013 - 18:18
fonte
3

Sto usando C qui, ma esistono operatori simili nella maggior parte delle lingue.

Supponi di avere una variabile per memorizzare i tipi:

unsigned char mytypes;

 #define TYPE_1  1
 #define TYPE_2  2
 #define TYPE_3  4
 #define TYPE_4  8

Per impostare uno dei tipi, devi utilizzare:

mytypes = mytypes | TYPE_1;

o, come una scorciatoia in C,

mytypes |= TYPE_1;

in entrambi i casi, i bit esistenti (tipi) presenti in mytypes sono conservati.

Per verificare se mytypes contenga un tipo specifico, dovresti scrivere:

if ((mytypes & TYPE_1) == TYPE_1)

Allo stesso modo, se volessi controllare due tipi contemporaneamente, dovresti scrivere:

if (((mytypes & (TYPE_1 | TYPE_3)) == (TYPE_1 | TYPE_3))

dove TYPE_1 | TYPE_3 è uguale a 5 come nell'esempio.

    
risposta data 04.07.2013 - 19:34
fonte

Leggi altre domande sui tag