2011-08-28 6 views
7

Ho iniziato a leggere "Programming Pearls" oggi e mentre facevo esercizio mi sono imbattuto in questa domanda "Come implementeresti il ​​tuo vettore bit?". Quando ho guardato la soluzione era così:Bit Utilizzo maschera nel programma di programmazione da Perle

#define BITSPERWORD 32 
#define SHIFT 5 
#define MASK 0x1F 
#define N 10000000 

int a[1 + N/BITSPERWORD]; 

void set(int i) { a[i >> SHIFT] |= (1 << (i & MASK)); 

Dove mi sto confuso in questa affermazione

1 << (i & MASK) 

Qualcuno potrebbe spiegare che cosa sta succedendo qui?

risposta

4

noti che MASK è impostato in modo che esso ha il più basso SHIFT bit impostati, dove SHIFT è esattamente il logaritmo a base 2 della BITSPERWORD.

Pertanto (i & MASK) selezionerà i bassi 5 bit di i, che è lo stesso che il resto dopo la divisione del 32 (basta considerare come prendendo i bassi due cifre di un numero decimale si dà il resto dopo la divisione per 100, per esempio). Che dà il numero del bit all'interno una parola che ci interessa.

1 << (i & MASK)) (che è, tra l'altro, un espressione, non un dichiarazione) ora crea un valore esattamente dove il bit ci interessa è impostato. L'unione di questo valore nella parola di memoria con |= imposterà il bit desiderato del vettore di bit.

+0

Grazie per la risposta Henning. Sarebbe valido se sostituissi '(i & MASK)' con '(i% 32)'? Se sarà valido ma non elegante, potresti per favore chiarire perché 'i & MASK' è preferito su' i% 32'? Molte grazie. – test123

+0

Sì - "i & MASK" e "i% 32" sono la stessa cosa se si è sicuri che "i" non è negativo. L'AND bit a bit è in genere più efficiente di una divisione con resto e pertanto è diventato la scelta tradizionale. O almeno per essere più efficiente quando i compilatori erano stupidi. Oggi puoi aspettarti che anche un compilatore moderatamente ottimizzante riscriva 'i% 32' su' i & 31' internamente in questo contesto (o può provare che 'i' non è negativo, nel qual caso la riscrittura è sempre sicura, oppure può pensare che un risultato negativo possa innescare comunque un comportamento indefinito nello spostamento). –

+0

Grande. Grazie mille per la spiegazione. – test123

2

0x20 è 32, quindi i & 0x1F assume i modulo 32, in modo da non spostarsi mai di 32 bit. Questa è una salvaguardia perché spostare qualsiasi cosa che non sia strettamente inferiore alla dimensione del tipo è un comportamento indefinito.

+0

Grazie per la risposta Kerrek! – test123