C ++: perché bool è lungo 8 bit?


132

In C ++, mi chiedo perché il tipo bool sia lungo 8 bit (sul mio sistema), dove è sufficiente solo un bit per contenere il valore booleano?

Credevo fosse per motivi di prestazioni, ma poi su una macchina a 32 o 64 bit, dove i registri sono larghi 32 o 64 bit, qual è il vantaggio in termini di prestazioni?

O è solo una di queste ragioni "storiche"?


9
Un bool non è 8 bit sul mio sistema. Sono 4 byte, lo stesso di un int.
Brian Neal,

21
l'ultima volta che qualcuno ha pensato a quello che stai pensando, abbiamo finito con std :: vector <bool>, la "caratteristica" stl più odiata di sempre =)
Viktor Sehr

1
jldupont, penso che tu mi abbia frainteso. Stavo chiedendo un sistema, dove sizeof(bool)sarebbe 4. Potrei giurare che msvc avesse bool a 32 bit, ma ho appena provato e non lo fa.
avakar,

7
Ad essere sinceri, il problema vector<bool>non è che cerca di essere intelligente e impacca i bool in pezzi, ma che cerca di farlo e si maschera da contenitore STL . Un semplice bitset andrebbe bene purché non pretenda di essere anche un contenitore STL.
jalf

2
@avakar: potresti confondere il booltipo di dati C ++ con il BOOLtipo di Windows a cui è stato digitato long. Quindi sizeof(bool) != sizeof(BOOL), che sono sicuro provoca molta confusione (e probabilmente un discreto numero di bug). Soprattutto perché ci sono anche booleane BOOLEANtypedefs in Windows, che sono alias per unsigned char. Inoltre, nota che mentre è comune boolessere 1 byte, lo standard C ++ ha una nota che indica specificamente che sizeof(bool)può essere più grande.
Michael Burr,

Risposte:


219

Perché ogni tipo di dati C ++ deve essere indirizzabile.

Come creeresti un puntatore a un singolo bit? Non puoi. Ma puoi creare un puntatore a un byte. Quindi un valore booleano in C ++ è in genere di dimensione byte. (Potrebbe anche essere più grande. Dipende dall'implementazione. La cosa principale è che deve essere indirizzabile, quindi nessun tipo di dati C ++ può essere più piccolo di un byte)


7
L'indirizzamento "byte" è una scelta architettonica (livello hw): si potrebbe benissimo progettare un sistema con una diversa "unità di indirizzamento". Per i processori comuni, indirizzare un "byte" finisce comunque per recuperare più di un "byte" dalla memoria esterna: ciò è dovuto a motivi di efficienza.
jldupont,

8
Sì, è una scelta hardware e se l'hardware lo consente, la dimensione di un bool potrebbe cambiare. Ma l'OP ha chiesto perché un bool ha una larghezza di 8 bit e sui sistemi in cui ciò accade, in genere è perché la CPU è in grado di indirizzare solo byte a 8 bit.
jalf

2
@jldupont: ci sono alcuni sistemi in cui gli indirizzi dei puntatori sono più dettagliati dei byte (ho già programmato sulla vecchia TI TMS34010 / 20, che utilizza puntatori bit-saggio), ma sono ECCEZIONALMENTE rari.
Michael Kohne,

1
Non sono sicuro cosa intendi. Ogni oggetto deve essere indirizzabile, ovvero deve essere possibile recuperare l'indirizzo di un oggetto. L'oggetto non deve memorizzare il proprio indirizzo. Un carattere ha in genere 8 bit di larghezza, sufficiente per memorizzare uno qualsiasi di 256 caratteri, ma ogni carattere ha anche un indirizzo definito da dove si trova in memoria. Ecco perché puoi creare un puntatore a un carattere.
jalf

88
Se posso contribuire con un'analogia poco chiara: ci sono otto piani nel mio edificio, ma l'ufficio postale non riconosce che si tratta di indirizzi diversi. Quindi, se voglio un indirizzo tutto per me, allora devo affittare l'intero edificio, anche se in realtà mi inserisco su un piano. Non sto usando gli altri sette piani per "memorizzare un indirizzo", sono solo costretto a sprecarli a causa della regola dell'ufficio postale che gli indirizzi si riferiscono agli edifici, non ai piani. Gli oggetti C ++ devono avere un indirizzo per se stessi - nessuna sala postale per ordinare la posta dopo la consegna ;-)
Steve Jessop,

39

La memoria è indirizzabile in byte. Non è possibile indirizzare un singolo bit, senza spostare o mascherare il byte letto dalla memoria. Immagino che questo sia un motivo molto grande.


1
Non sempre. L'MCU 8051, ad esempio, ha 16 byte di posizioni indirizzabili in bit
Beached il

20

Un booleantipo normalmente segue la più piccola unità di memoria indirizzabile della macchina target (cioè solitamente il byte di 8 bit).

L'accesso alla memoria è sempre in "blocchi" (più parole, questo per efficienza a livello hardware , transazioni del bus): un bit booleano non può essere indirizzato "da solo" nella maggior parte dei sistemi CPU. Naturalmente, una volta che i dati sono contenuti in un registro , ci sono spesso istruzioni specializzate per manipolare i bit in modo indipendente.

Per questo motivo, è abbastanza comune usare tecniche di "bit packing" per aumentare l'efficienza nell'uso di tipi di dati di base "booleani". Una tecnica come enum(in C) con una potenza di 2 codifica è un buon esempio. Lo stesso tipo di trucco si trova nella maggior parte delle lingue.

Aggiornato : grazie a un'eccellente discussione, è stato portato alla mia attenzione che sizeof(char)==1per definizione in C ++. Quindi, l'indirizzamento di un tipo di dati "booleano" è piuttosto legato alla più piccola unità di memoria indirizzabile (rafforza il mio punto).


Per tutti i commenti lasciati a riguardo, è impressionante che tu abbia lasciato fuori la parte più importante della risposta: un booltipo segue la più piccola unità di memoria allocabile perché C ++ richiede che sia possibile creare puntatori ad essa . Senza tale requisito, a boolavrebbe potuto essere immaginato come un singolo bit anche su macchine indirizzabili con byte correnti.
jalf

1
hmmm ... Potrei creare un'architettura CPU in cui un po 'potrebbe essere indirizzabile ... Potrei persino scrivere un compilatore ecc. per questo. Potrei avere una regione di memoria speciale (o qualsiasi altra cosa) che sarebbe "un po 'indirizzabile". Non è impossibile in alcun modo l'immaginazione.
jldupont,

2
Sì, e su quel sistema, un bool potrebbe essere reso un singolo bit. Ma l'OP non ha chiesto "perché è un bool 8 bit largo su CPU ipotetica jlduponts". Ha chiesto informazioni sulle CPU correnti, comuni e di tutti i giorni, e su quelle è perché sono indirizzabili in byte.
jalf

4
sizeof (char) == 1 per definizione in C ++, quindi ciò che il tuo hardware può o non può fare non è rilevante. Non puoi avere sizeof (bool) <sizeof (char). BTW C ++ è definito in modo tale da poter avere un puntatore "fat" per indirizzare alcune subunità di ciò che l'hardware può indirizzare se non è conveniente avere char l'unità hardware più piccola indirizzabile. Questo è stato usato almeno in alcuni compilatori C per architetture indirizzabili di parole vecchie.
Programmatore

@AProgrammer:: sizeof(char)==1 definitionquesto è il miglior contrappunto alla mia argomentazione. Grazie!
jldupont,

6

Le risposte su 8 bit che rappresentano la minima quantità di memoria indirizzabile sono corrette. Tuttavia, alcune lingue possono usare 1 bit per i booleani, in un certo senso. Mi sembra di ricordare che Pascal abbia implementato i set come stringhe di bit. Cioè, per il seguente set:

{1, 2, 5, 7}

Potresti avere questo in memoria:

01100101

Ovviamente puoi fare qualcosa di simile in C / C ++ se vuoi. (Se stai tenendo traccia di un gruppo di booleani, potrebbe avere senso, ma dipende davvero dalla situazione.)


8
In effetti, C ++ lo fa con il vettore contenitore specializzato <bool> - è comunemente visto come un disastro.

C ++ lo fa anche con "campi di bit", ereditati da C. Quando si dichiara una variabile membro di una struttura / classe, è possibile dichiarare il numero di bit utilizzati per memorizzare il valore (ad es. "Campo breve senza segno: 3").

@Neil: perché è comunemente visto come un disastro? È un problema di prestazioni?
Jérôme,

2
@ Jerome: È perché, poiché un po 'non è indirizzabile, non può comportarsi come un normale vector. In realtà non è un contenitore di tipo STL, perché ci sono vincoli sul comportamento. Quel che è peggio è che causa problemi con qualcuno che ha boole vuole farne uno vector. È un comportamento sorprendente, e non è quello che vuoi in una lingua.
David Thornley,

1
@jldupont - è sufficiente fare una cosa del genere una volta. E C ++ non garantisce che i bit siano indirizzabili (piuttosto il contrario), non importa di cosa sia capace l'hardware.

1

So che è vecchio ma ho pensato di buttare i miei 2 centesimi.

Se si limita il valore booleano o il tipo di dati a un bit, l'applicazione è a rischio di curruption della memoria. Come gestite le statistiche di errore in memoria lunghe solo un po '?

Sono andato a un colloquio di lavoro e una delle affermazioni che il responsabile del programma mi ha detto era: "Quando inviamo il segnale per lanciare un missle, inviamo un semplice bit di attivazione via wireless. L'invio di un bit è estremamente veloce e noi bisogno che quel segnale sia il più veloce possibile ".

Bene, è stato un test per capire se ho capito concetti e bit, byte e gestione degli errori. Quanto sarebbe facile per un cattivo inviare un messaggio. O cosa succede se durante la trasmissione il bit viene capovolto dall'altra parte.


Poni nuova domanda , non pubblicare la tua domanda come risposta ad altre domande.
Igor Jerosimić,

6
Penso che la domanda contenuta in questa "risposta" sia in realtà retorica, cioè il motivo per cui non implementiamo i booleani come un bit è perché un singolo bit non è in grado di gestire le statistiche di errore.
Stephen Holt,

1
@StephenHolt ma non è questo il motivo e TBH questa risposta non ha alcun senso.
doc,

1
...che cosa? Non so cosa intendi per "statistiche di errore", se CRC o simili, o rappresentazioni di trap. Ma in ogni caso, anche i tipi più grandi non usano i loro bit extra "di riserva" per "statistiche di errore" poiché tutti, tranne i programmatori di ambienti estremi, presumono giustamente che il loro hardware sia in grado di gestire il rilevamento / correzione degli errori prima che il loro codice legga la memoria, quindi non è necessario passare il loro tempo in qualche modo riempiendo ogni variabile con informazioni di verifica o altro. Non è per questo che boolusa 8 bit sulla macchina di OP e 32 sui miei, dato che gli altri 7 o 31 bit non sono certamente usati per alcuna "statistica di errore". Questo non ha senso
underscore_d il

1

Alcuni compilatori incorporati hanno un tipo int1 che viene utilizzato per il bit-pack di flag booleani (ad esempio serie CCS di compilatori C per MPU Microchip). L'impostazione, la cancellazione e il test di queste variabili utilizzano istruzioni a livello di bit a singola istruzione, ma il compilatore non consentirà altre operazioni (ad esempio, prendendo l'indirizzo della variabile), per i motivi indicati in altre risposte.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.