2012-01-19 10 views
17

Desidero una funzione C semplice che restituirà true se il bit n-esimo in un byte è impostato su 1. Altrimenti restituirà false.una funzione per verificare se l'ennesimo bit è impostato in un byte

Questa è una funzione critica in termini di tempo di esecuzione, quindi sto pensando al modo più ottimale per farlo.

+1

duplicato, http://stackoverflow.com/questions/523724/cc-check-if-one-bit-is -set-in-ie-int-variable – blueshift

+4

Questo non è un problema, ha chiesto in particolare i metodi ** non-bitshift **. – paxdiablo

risposta

32

La seguente funzione può fare ciò è necessario:

int isNthBitSet (unsigned char c, int n) { 
    static unsigned char mask[] = {128, 64, 32, 16, 8, 4, 2, 1}; 
    return ((c & mask[n]) != 0); 
} 

Questa assume byte di 8 bit (non un dato in C) e il bit zeroth essendo dell'ordine più alto. Se queste ipotesi non sono corrette, si tratta semplicemente di espandere e/o riordinare l'array mask.

Nessun controllo degli errori viene eseguito poiché si è citato la velocità come la considerazione più importante. Non inviare non pass in uno n non valido, il comportamento sarà indefinito.

A folle livello di ottimizzazione -O3, gcc ci dà:

isNthBitSet: pushl %ebp 
       movl %esp, %ebp 
       movl 12(%ebp), %eax 
       movzbl 8(%ebp), %edx 
       popl %ebp 
       testb %dl, mask(%eax) 
       setne %al 
       movzbl %al, %eax 
       ret 
mask:   .byte -128, 64, 32, 16, 8, 4, 2, 1 

che è piuttosto piccolo ed efficiente. E se lo rendi statico e suggerisci l'inlining, o lo imponi in linea come una definizione di macro, puoi anche bypassare il costo di una chiamata di funzione.

Assicurati solo di confrontare qualsiasi soluzione che ti è stata fornita, incluso questo (a). Il mantra numero uno nell'ottimizzazione è "Misura, non indovinare!"

Se si desidera sapere come funzionano gli operatori bit a bit, vedere here. La versione semplificata AND-only è sotto.

L'operazione AND & imposterà un bit nella destinazione solo se entrambi i bit sono impostati nelle sorgenti tewo. Relativa tabella è:

AND | 0 1 
----+---- 
0 | 0 0 
1 | 0 1 

Per un dato valore char, usiamo le maschere bit singolo bit per verificare se un bit è impostato. Diciamo che hai il valore 13 e vuoi vedere se è impostato il bit dal terzo meno significativo.

Decimal Binary 
    13  0000 1101 
    4  0000 0100 (the bitmask for the third-from-least bit). 
     ========= 
     0000 0100 (the result of the AND operation). 

Si può vedere che tutti i bit zero nella maschera danno come risultato zero bit di risultato equivalenti. Il singolo bit della maschera lascerà fondamentalmente il bit equivalente nel flusso del valore fino al risultato. Il risultato è quindi zero se il bit che stiamo verificando era zero o diverso da zero se era uno.

Ecco da dove viene l'espressione nell'istruzione return. I valori nella tabella di ricerca mask sono tutte le maschere single-bit:

Decimal Binary 
    128 1000 0000 
    64 0100 0000 
    32 0010 0000 
    16 0001 0000 
    8 0000 1000 
    4 0000 0100 
    2 0000 0010 
    1 0000 0001 

(a)I so quanto sono bravo, ma non lo faccio :-)

+2

Tabella di ricerca, sì! Ma mi aspetterei che il bit 0 sia il bit meno significativo nel byte, e quindi avremmo invertito l'ordine delle voci intializzate di 'mask []'. – hardmath

+0

Non sempre, @hardmath, molti standard di comunicazione riempiono i loro ottetti dalla "sinistra". Come te, preferisco pensare a b0 come il meno significativo. – paxdiablo

+0

-1, prolisso e soggetto a errori di scrittura, informazioni sul cambio di bit. – blueshift

20

Basta controllare il valore di (1 << bit) & byte. Se è diverso da zero, il bit è impostato.

3
bool isSet(unsigned char b, unsigned char n) { return b & (1 << n); } 
+0

Capisco 'char unsigned 'per il valore byte, ma' n'? Sembra strano. – Rob

+0

well n non può essere più grande di un byte ... non ha molta importanza –

+0

Dato che 'unsigned char' non limita solo valori validi, direi che è un [piccolo]" odore di codice "per quanto riguarda alla leggibilità. Certo, è discutibile e sono d'accordo che non importa molto. – Rob

8

Lasciare il numero num. Poi:

return ((1 << n) & num); 
+0

Puoi spiegare questo codice? – vidyasagarr7

2
#include<stdio.h> 
int main() 
{ 
    unsigned int n,a; 
    printf("enter value for n\n"); 
    scanf("%u",&n); 
    pintf("enter value for a:\n"); 
    scanf("%u",&a); 
    a= a|(((~((unsigned)0))>>(sizeof(int)*8-1))<<n); 
    printf("%u\n",a); 
} 
2

altro approccio sarebbe

bool isNthBitSet (unsigned char c, int n) { 
     return (1 & (c >> n)); 
    } 
0
#include<stdio.h> 

int main() 
{ 
     int data,bit; 
     printf("enter data:"); 
     scanf("%d",&data); 
     printf("enter bit position to test:"); 
     scanf("%d",&bit); 
     data&(1<<bit)?printf("bit is set\n"):printf("bit is clear\n"); 

    return 0; 
} 
+2

Questo codice solo-risposta richiede alcune spiegazioni per rendere il valore aggiunto più ovvio, in relazione ad altre risposte più vecchie, potenziate e meglio spiegate (non implicando che tutte le altre risposte siano meglio spiegate ...). – Yunnosch

Problemi correlati