2010-10-22 7 views
13

Desidero memorizzare i bit in una matrice (come la struttura). Così posso seguire uno dei seguenti due approcciBit field vs Bitset

numero Approccio 1 (AN 1)

struct BIT 
{ 
    int data : 1 
}; 

int main() 
{ 
    BIT a[100]; 
    return 0; 
} 

numero Approccio 2 (AN 2)

int main() 
{ 
    std::bitset<100> BITS; 
    return 0; 
} 

Perché qualcuno dovrebbe preferire un 2 su una 1?

+3

per citare pagina cplusplus.com su bitset, "La classe è molto simile a una serie regolare, ma ottimizzando l'allocazione dello spazio". Se i tuoi int sono 4 byte, un set di bit utilizza 32 volte meno spazio. – AlcubierreDrive

+2

La struttura 'BIT' sarà allineata comunque a (almeno) un byte. – Archie

+0

@Jon, postalo come risposta. (È un buon punto.) –

risposta

15

Perché approccio nr. 2 utilizza effettivamente 100 bit di memoria, oltre a un overhead (costante) molto minore, mentre nr. 1 in genere utilizza quattro byte di archiviazione per la struttura Bit. In generale, un struct è almeno un byte grande per lo standard C++.

#include <bitset> 
#include <iostream> 

struct Bit { int data : 1; }; 

int main() 
{ 
    Bit a[100]; 
    std::bitset<100> b; 
    std::cout << sizeof(a) << "\n"; 
    std::cout << sizeof(b) << "\n"; 
} 

stampe

400 
16 

Oltre a questo, bitset avvolge l'array bit in una rappresentazione oggetto bello, con molte operazioni utili.

+0

Come mai l'output di 'sizeof (b)' è 16? 100 bit significa 100/8 byte. Cosa mi manca? – CLOWN

+1

Deve essere "arrotondato" a un multiplo di otto, poiché un byte è la più piccola unità di memoria direttamente indirizzabile. Prova a compilare con 128 bit nel set, poi è ancora 16. 'bitset' usa alcuni accorgimenti per far finta che in realtà stia indirizzando bit .. –

+0

Il mio commento precedente era a metà destra. È arrotondato a un multiplo di 4 byte, poiché un'unità a quattro byte è la più veloce da elaborare per un computer a 32 bit. Ma in ogni caso, un byte è la più piccola unità indirizzabile, quindi è almeno 13 (100/8 = 12,5 e mezzo byte non è indirizzabile). Scusa, venerdì pomeriggio. –

0

L'approccio numero 1 verrà probabilmente compilato come una matrice di numeri interi a 4 byte e un bit di ciascuno verrà utilizzato per memorizzare i dati. Teoricamente un compilatore intelligente potrebbe ottimizzarlo, ma non ci conterei.

C'è un motivo per cui non si desidera utilizzare std::bitset?

0

Per quotare cplusplus.com's page on bitset, "La classe è molto simile a un array normale, ma ottimizza l'allocazione dello spazio". Se i tuoi int sono 4 byte, un set di bit utilizza 32 volte meno spazio.

Anche l'esecuzione di bool bits[100], come suggerito da sbi, è ancora peggio di bitset, poiché la maggior parte delle implementazioni presenta bool> = 1 byte.

Se, per motivi di curiosità intellettuale solo, si voleva implementare il proprio bitset, si potrebbe farlo utilizzando maschere di bit:

typedef struct { 
    unsigned char bytes[100]; 
} MyBitset; 

bool getBit(MyBitset *bitset, int index) 
{ 
    int whichByte = index/8; 
    return bitset->bytes[whichByte] && (1 << (index = % 8)); 
} 

bool setBit(MyBitset *bitset, int index, bool newVal) 
{ 
    int whichByte = index/8; 

    if (newVal) 
    { 
    bitset->bytes[whichByte] |= (1 << (index = % 8)); 
    } 
    else 
    { 
    bitset->bytes[whichByte] &= ~(1 << (index = % 8)); 
    } 
} 

(spiacenti per l'utilizzo di una struttura invece di una classe per la via. Sto pensando direttamente al C perché mi trovo nel bel mezzo di un incarico a basso livello per la scuola Ovviamente due enormi vantaggi dell'utilizzo di una classe sono l'overloading dell'operatore e la possibilità di disporre di un array di dimensioni variabili.

+3

In C++ l'unica differenza tra una classe e struct è che i membri della classe sono privati ​​per impostazione predefinita e che i membri struct sono pubblici per impostazione predefinita. – M2tM

5

Una buona scelta dipende da come userete i bit.

std::bitset<N> è di dimensione fissa. Visual C++ 10.0 è wrt non conforme. ai costruttori; in generale devi fornire una soluzione alternativa. Questo è stato, ironia della sorte, a causa di ciò che Microsoft pensava fosse una correzione di bug - hanno introdotto un costruttore che prendeva argomento int, come ricordo.

std::vector<bool> è ottimizzato allo stesso modo di std::bitset. Costo: l'indicizzazione non fornisce direttamente un riferimento (non ci sono riferimenti a singoli bit in C++), ma restituisce invece un oggetto proxy, che non è qualcosa che si nota finché non si tenta di utilizzarlo come riferimento. Vantaggio: spazio di archiviazione minimo e il vettore può essere ridimensionato secondo necessità.

Semplicemente usando per es. unsigned è anche un'opzione, se hai intenzione di gestire un piccolo numero di bit (in pratica 32 o meno, sebbene la garanzia formale sia solo di 16 bit).

Infine, TUTTI gli identificatori UPPERCASE sono per convenzione (tranne Microsoft) riservati per macro, al fine di ridurre la probabilità di collisioni di nomi. Pertanto è una buona idea non utilizzare TUTTI gli identificatori UPPERCASE per nient'altro che le macro. E per usare sempre gli identificatori di TUTTO MAIUSCOLO per i macro (questo rende anche più facile riconoscerli).

Acclamazioni & hth.,