2013-03-06 18 views
10

Sto riscontrando un piccolo problema nell'acquisire n bit da un byte.Grabbing n bit da un byte

Ho un numero intero senza segno. Diciamo che il nostro numero in esadecimale è 0x2A, che è 42 in decimale. In binario appare così: 0010 1010. Come faccio ad afferrare i primi 5 bit che sono 00101 ei successivi 3 bit che sono 010, e li collochiamo in interi separati?

Se qualcuno potesse aiutarmi sarebbe bello! Io so come estrarre da un byte, che è quello di fare semplicemente

int x = (number >> (8*n)) & 0xff // n being the # byte 

che ho visto su un altro post su stack overflow, ma non ero sicuro su come ottenere i bit separati fuori del byte. Se qualcuno potesse aiutarmi, sarebbe fantastico! Grazie!

+0

I primi 5 bit (MSB) di 42 sono 00000 perché int è sempre più di 1 byte. Inoltre, non esiste nulla come numero intero senza segno che ha la forma decimale di un esagono. 'int a = 0x2A;' equivale a scrivere 'int a = 42;' – user93353

risposta

14

integer sono rappresentati all'interno di una macchina come una sequenza di bit; Fortunatamente per noi umani, i linguaggi di programmazione forniscono un meccanismo per mostrarci questi numeri in decimale (o esadecimale), ma questo non altera la loro rappresentazione interna.

Si dovrebbe rivedere gli operatori bit per bit &, |, ^ e ~ così come gli operatori di spostamento << e >>, che vi aiuterà a capire come risolvere i problemi di questo tipo.

Gli ultimi 3 bit del numero intero sono:

x & 0x7 

I cinque bit a partire dal otto ultimo bit sono:

x >> 3 // all but the last three bits 
    & 0x1F // the last five bits. 
+0

In che modo questo confronta le prestazioni con la semplice memorizzazione dei due sub-ints come due interi a 32 bit? L'estrazione richiederà del tempo, ma le operazioni sono 32 più lente? – Kammeot

+0

@InspiredOne: domande come questa sono impossibili da rispondere con precisione in astratto, ma è ovvio che migliora l'utilizzo della memoria (di un fattore di otto rispetto a due numeri interi a 32 bit o di un fattore due rispetto a due byte) migliora le prestazioni della cache, il throughput della memoria e la larghezza di banda, se pertinente (tempo di trasmissione o storage secondario). Poiché il costo della CPU è insignificante rispetto a uno qualsiasi di questi fattori, i dati compressi saranno normalmente più veloci a condizione che siano necessarie molte istanze; non vale la pena farlo per un singolo paio di variabili (ma non fa neanche male). – rici

1

basta sbarazzarsi di 8 * nel codice.

int input = 42; 
int high3 = input >> 5; 
int low5 = input & (32 - 1); // 32 = 2^5 
bool isBit3On = input & 4; // 4 = 2^(3-1) 
1

int x = (number >> 3) & 0x1f;

vi darà un intero dove gli ultimi 5 bit sono gli 8-4 bit di number e gli zeri negli altri bit.

Analogamente,

int y = number & 0x7;

vi darà un numero intero con gli ultimi 3 bit impostati gli ultimi 3 bit di number e gli zeri nel resto.

7

Dire che vuoi hi bit dall'alto e lo bit dal basso. (5 e 3 nel tuo esempio)

top = (n >> lo) & ((1 << hi) - 1) 
bottom = n & ((1 << lo) - 1) 

Spiegazione:

Per la superiore, prima sbarazzarsi dei bit inferiori (sposta a destra), quindi mascherare i restanti con una maschera di "tutti quelli" (se avete un numero binario come 0010000, sottraendo un risultato 0001111 - lo stesso numero di 1 s come avete avuto 0 -s nel numero originale).

Per il fondo è lo stesso, basta non preoccuparsi del cambio iniziale.

top = (42 >> 3) & ((1 << 5) - 1) = 5 & (32 - 1) = 5 = 00101b 
bottom = 42 & ((1 << 3) - 1) = 42 & (8 - 1) = 2 = 010b 
12

"afferrare" le parti di un tipo intero in C funziona così:

  1. Si spostano i bit che si desidera nella posizione più bassa.
  2. Si utilizza & per mascherare i bit che si desidera - quelle significa "copia questo bit", zeri significano "ignorano"

Così, in te esempio. Diciamo che abbiamo un numero int x = 42;

primi 5 bit:

(x >> 3) & ((1 << 5)-1); 

o

(x >> 3) & 31; 

per andare a prendere i più bassi tre bit:

(x >> 0) & ((1 << 3)-1) 

o:

x & 7; 
2

A questo scopo è possibile utilizzare i bitfield. I bitfield sono strutture speciali in cui è possibile specificare le variabili in bit.

typedef struct { 
    unsigned char a:5; 
    unsigned char b:3; 
} my_bit_t; 

unsigned char c = 0x42; 
my_bit_t * n = &c; 
int first = n->a; 
int sec = n->b; 

campi di bit sono descritti più in dettaglio http://www.cs.cf.ac.uk/Dave/C/node13.html#SECTION001320000000000000000

Il fascino di campi di bit è, che non si ha a che fare con operatori di spostamento, ecc La notazione è abbastanza facile. Come sempre con la manipolazione di bit, c'è un problema di portabilità.