C ++: Warum ist Bool 8 Bit lang?


132

In C ++ frage ich mich, warum der Bool-Typ 8 Bit lang ist (auf meinem System), wobei nur ein Bit ausreicht, um den Booleschen Wert zu speichern.

Früher glaubte ich, dies sei aus Leistungsgründen der Fall, aber was ist dann auf einem 32-Bit- oder 64-Bit-Computer, auf dem die Register 32 oder 64 Bit breit sind, der Leistungsvorteil?

Oder ist es nur einer dieser "historischen" Gründe?


9
Ein Bool ist auf meinem System nicht 8-Bit. Es sind 4 Bytes, genau wie bei einem Int.
Brian Neal

21
Das letzte Mal, als jemand dachte, was Sie denken, landeten wir mit std :: vector <bool>, dem am meisten gehassten stl "Feature" aller Zeiten =)
Viktor Sehr

1
jldupont, ich denke du hast mich falsch verstanden. Ich habe nach einem System gefragt, wo sizeof(bool)es 4 geben würde. Ich könnte schwören, dass msvc 32-Bit-Bools hat, aber ich habe es nur versucht und es nicht.
Avakar

7
Um fair zu sein, besteht das Problem vector<bool>nicht darin, dass es versucht, klug zu sein und Bools in Stücke zu packen, sondern dass es versucht, dies zu tun und sich als STL-Container zu tarnen . Ein einfaches Bitset wäre in Ordnung gewesen, solange es nicht auch vorgibt, ein STL-Container zu sein.
Jalf

2
@avakar - Möglicherweise verwechseln Sie den C ++ - boolDatentyp mit dem Windows- BOOLTyp, auf den typisiert ist long. Also sizeof(bool) != sizeof(BOOL), was sicher viel Verwirrung stiftet (und wahrscheinlich eine ganze Reihe von Fehlern). Zumal es auch booleanund BOOLEANtypedefs in Windows gibt, die Aliase für sind unsigned char. Beachten Sie außerdem, dass boolder C ++ - Standard zwar 1 Byte enthält, der Hinweis jedoch ausdrücklich angibt, sizeof(bool)dass er größer sein kann.
Michael Burr

Antworten:


219

Weil jeder C ++ - Datentyp adressierbar sein muss.

Wie würden Sie einen Zeiger auf ein einzelnes Bit erstellen? Das kannst du nicht. Sie können jedoch einen Zeiger auf ein Byte erstellen. Ein Boolescher Wert in C ++ hat also normalerweise die Größe von Bytes. (Es kann auch größer sein. Das hängt von der Implementierung ab. Hauptsache, es muss adressierbar sein, damit kein C ++ - Datentyp kleiner als ein Byte sein kann.)


7
"Byte" -Adressierung ist eine architektonische Wahl (hw-Ebene): Man könnte sehr gut ein System mit einer anderen "Adressierungseinheit" entwerfen. Bei herkömmlichen Prozessoren führt das Adressieren eines "Bytes" ohnehin dazu, dass mehr als ein "Byte" aus dem externen Speicher abgerufen wird. Dies liegt an Effizienzgründen.
Jldupont

8
Ja, es ist eine Hardware-Wahl, und wenn die Hardware dies zulässt, kann sich die Größe eines Bools ändern. Das OP fragte jedoch, warum ein Bool 8 Bit breit ist, und auf Systemen, auf denen dies der Fall ist, liegt dies im Allgemeinen daran, dass die CPU nur 8-Bit-Bytes adressieren kann.
Jalf

2
@jldupont: Es gibt einige Systeme, in denen Zeigeradressen feiner als Bytes sind (ich habe zuvor auf dem alten TI TMS34010 / 20 programmiert, der bitweise Zeiger verwendet), aber sie sind außerordentlich selten.
Michael Kohne

1
Nicht sicher was du meinst. Jedes Objekt muss adressierbar sein, dh es muss möglich sein, die Adresse eines Objekts abzurufen. Das Objekt muss keine eigene Adresse speichern. Ein Zeichen ist normalerweise 8 Bit breit und reicht aus, um 256 Zeichen zu speichern. Jedes Zeichen hat jedoch auch eine Adresse, die durch die Position im Speicher definiert wird. Deshalb können Sie einen Zeiger auf ein Zeichen erstellen.
Jalf

88
Wenn ich eine zwielichtige Analogie beisteuern darf: Es gibt acht Stockwerke in meinem Gebäude, aber die Post erkennt nicht an, dass es sich um unterschiedliche Adressen handelt. Wenn ich also eine Adresse für mich allein haben möchte, muss ich das gesamte Gebäude mieten, obwohl ich tatsächlich auf eine Etage passe. Ich verwende die anderen sieben Stockwerke nicht zum "Speichern einer Adresse", sondern bin nur gezwungen, sie zu verschwenden, da sich die Postregel auf Gebäude bezieht, nicht auf Stockwerke. C ++ - Objekte müssen eine Adresse für sich haben - keine Posträume, um die Post nach der Zustellung zu sortieren ;-)
Steve Jessop

39

Der Speicher ist byteadressierbar. Sie können kein einzelnes Bit adressieren, ohne das aus dem Speicher gelesene Byte zu verschieben oder zu maskieren. Ich würde mir vorstellen, dass dies ein sehr großer Grund ist.


1
Nicht immer. Die 8051 MCU hat zum Beispiel 16 Bytes
Beached

20

Ein booleanTyp folgt normalerweise der kleinsten Einheit des adressierbaren Speichers des Zielcomputers (dh normalerweise dem 8-Bit-Byte).

Der Zugriff auf den Speicher erfolgt immer in "Blöcken" (mehrere Wörter, dies dient der Effizienz auf Hardwareebene , Bustransaktionen): Ein Boolesches Bit kann in den meisten CPU-Systemen nicht "allein" adressiert werden. Sobald die Daten in einem Register enthalten sind , gibt es natürlich häufig spezielle Anweisungen, um Bits unabhängig voneinander zu manipulieren.

Aus diesem Grund ist es durchaus üblich, Techniken des "Bitpackens" zu verwenden, um die Effizienz bei der Verwendung von "booleschen" Basisdatentypen zu erhöhen. Eine Technik wie enum(in C) mit einer Potenz von 2 Codierung ist ein gutes Beispiel. Die gleiche Art von Trick findet man in den meisten Sprachen.

Aktualisiert : Dank einer hervorragenden Diskussion wurde ich darauf aufmerksam gemacht, dass sizeof(char)==1per Definition in C ++. Daher ist die Adressierung eines "booleschen" Datentyps ziemlich an die kleinste Einheit des adressierbaren Speichers gebunden (was meinen Standpunkt verstärkt).


Bei allen Kommentaren, die Sie dazu hinterlassen haben, ist es beeindruckend, dass Sie den wichtigsten Teil der Antwort ausgelassen haben: Ein boolTyp folgt der kleinsten Einheit des zuweisbaren Speichers, da C ++ erfordert, dass es möglich sein muss, Zeiger darauf zu erstellen . Ohne diese Anforderung boolhätte a möglicherweise auch auf aktuellen byteadressierbaren Maschinen als ein einziges Bit dargestellt werden können.
Jalf

1
hmmm ... ich könnte eine CPU-Architektur erstellen, in der ein bisschen adressierbar sein könnte ... ich könnte sogar einen Compiler usw. dafür schreiben. Ich könnte einen speziellen Speicherbereich (oder was auch immer) haben, der "bitadressierbar" wäre. Es ist keineswegs unmöglich.
Jldupont

2
Ja, und auf diesem System könnte ein Bool zu einem einzelnen Bit gemacht werden. Aber das OP fragte nicht "warum ist ein Bool 8 Bit breit auf jlduponts hypothetischer CPU". Er fragte nach aktuellen, gängigen, alltäglichen CPUs, und auf diesen liegt es daran, dass sie byteadressierbar sind.
Jalf

4
sizeof (char) == 1 pro Definition in C ++. Was Ihre Hardware also kann oder nicht kann, ist nicht relevant. Sie können nicht sizeof (bool) <sizeof (char) haben. BTW C ++ ist so definiert, dass Sie einen "fetten" Zeiger haben können, um eine Untereinheit dessen zu adressieren, was die Hardware adressieren kann, wenn es nicht bequem ist, char die kleinste hardwareadressierbare Einheit zu haben. Dies wurde zumindest in einigen C-Compilern für alte wortadressierbare Architekturen verwendet.
AProgrammer

@AProgrammer :: sizeof(char)==1 definitiondas ist das beste Gegenargument zu meiner Argumentation. Vielen Dank!
Jldupont

6

Die Antworten, dass 8-Bit die kleinste speicherbare Speichermenge ist, sind korrekt. Einige Sprachen können jedoch in gewisser Weise 1-Bit für Boolesche Werte verwenden. Ich erinnere mich an Pascals Implementierung von Sets als Bitstrings. Das heißt, für den folgenden Satz:

{1, 2, 5, 7}

Sie könnten dies im Speicher haben:

01100101

Sie können in C / C ++ natürlich etwas Ähnliches tun, wenn Sie möchten. (Wenn Sie eine Reihe von Booleschen Werten im Auge behalten, könnte dies sinnvoll sein, aber es hängt wirklich von der Situation ab.)


8
Tatsächlich tut C ++ dies mit dem spezialisierten Containervektor <bool> - dies wird häufig als Katastrophe angesehen.

C ++ tut dies auch mit "Bitfeldern", die von C geerbt wurden. Wenn Sie eine Mitgliedsvariable einer Struktur / Klasse deklarieren, können Sie die Anzahl der Bits deklarieren, die zum Speichern des Werts verwendet werden (z. B. "vorzeichenloses kurzes Feld: 3").

@Neil: Warum wird es allgemein als Katastrophe angesehen? Ist es ein Leistungsproblem?
Jérôme

2
@ Jerome: Das liegt daran, dass sich ein Bit nicht adressierbar verhält, da es nicht adressierbar ist vector. Es handelt sich eigentlich nicht um einen STL-Container, da das Verhalten Einschränkungen unterliegt. Schlimmer ist, dass es Probleme mit jemandem verursacht, der bools hat und einen daraus machen vectorwill. Es ist ein überraschendes Verhalten, und das ist nicht das, was Sie in einer Sprache wollen.
David Thornley

1
@jldupont - es reicht aus, einmal so einen Punkt zu machen. Und C ++ übernimmt keine Garantie dafür, dass Bits adressierbar sind (eher umgekehrt), unabhängig davon, wozu die Hardware in der Lage ist.

1

Ich weiß, dass das alt ist, aber ich dachte, ich würde meine 2 Cent einwerfen.

Wenn Sie Ihren Booleschen Wert oder Datentyp auf ein Bit beschränken, besteht für Ihre Anwendung das Risiko eines Speicherausfalls. Wie gehen Sie mit Fehlerstatistiken im nur ein Bit langen Speicher um?

Ich ging zu einem Vorstellungsgespräch und eine der Aussagen des Programmleiters lautete: "Wenn wir das Signal zum Starten einer Rakete senden, senden wir einfach ein einfaches Ein-Bit-Ein-Aus-Bit über Funk. Das Senden eines Bits ist extrem schnell und wir brauche dieses Signal, um so schnell wie möglich zu sein. "

Nun, es war ein Test, um zu sehen, ob ich die Konzepte und Bits, Bytes und die Fehlerbehandlung verstanden habe. Wie einfach wäre es für einen Bösen, eine 1-Bit-Nachricht zu versenden. Oder was passiert, wenn das Bit während der Übertragung in die andere Richtung gedreht wird?


Stellen Sie eine neue Frage , stellen Sie Ihre Frage nicht als Antwort auf andere Fragen.
Igor Jerosimić

6
Ich denke, die in dieser "Antwort" enthaltene Frage ist tatsächlich eine rhetorische, dh der Grund, warum wir Boolesche Werte nicht als ein Bit implementieren, ist, dass ein einzelnes Bit keine Fehlerstatistiken verarbeiten kann.
Stephen Holt

1
@ StephenHolt, aber das ist nicht der Grund und TBH diese Antwort macht keinen Sinn.
Doc

1
...Was? Ich weiß nicht, was Sie unter "Fehlerstatistiken" verstehen, ob CRCs oder ähnliches oder Trap-Darstellungen. Aber auf jeden Fall verwenden selbst die größeren Typen ihre zusätzlichen "Ersatz" -Bits nicht für "Fehlerstatistiken", da alle Codierer mit Ausnahme extremer Umgebungen zu Recht davon ausgehen, dass ihre Hardware die Fehlererkennung / -korrektur handhaben kann, bevor ihr Code jemals Speicher liest Sie müssen ihre Zeit nicht damit verbringen, jede Variable mit Verifizierungsinformationen oder was auch immer aufzufüllen. Das ist nicht der Grund, warum bool8 Bits auf dem OP-Computer und 32 auf meinem verwendet werden, da diese anderen 7 oder 31 Bits sicherlich nicht für "Fehlerstatistiken" verwendet werden. Das macht keinen Sinn
underscore_d

1

Einige eingebettete Compiler haben einen int1-Typ, der zum Bitpacken von booleschen Flags verwendet wird (z. B. CC-Serie von C-Compilern für Microchip-MPUs). Das Setzen, Löschen und Testen dieser Variablen verwendet Befehle auf Bitebene mit einem Befehl, aber der Compiler lässt aus den in anderen Antworten angegebenen Gründen keine anderen Operationen zu (z. B. die Adresse der Variablen zu übernehmen).

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.