Ich weiß, Sie können einfach #define einige Ganzzahlen, aber warum hatte C vor C99 keinen dedizierten booleschen Datentyp?
Es ist ein so häufiges Vorkommen in der Programmierung und Logik, dass ich das Fehlen eines expliziten Typs und einer expliziten Notation nicht verstehe.
-1: Welches Problem wird durch die Kenntnis der Implementierungsdetails von Kernighan und Ritchie in C gelöst?
– S. Lott
11. März 2010 um 15:07 Uhr
@S.Lott – Entschuldigung, habe ich den Zweck von StackOverflow nicht verstanden? Ist diese Frage nicht programmierbezogen? Aus den FAQ: “Dies ist ein Ort für Fragen, die beantwortet werden können.” “Solange Ihre Frage … detailliert und spezifisch ist, klar und einfach geschrieben ist und für mindestens einen anderen Programmierer irgendwo von Interesse ist.” Was habe ich noch verpasst?
– Andy Shellam
11. März 2010 um 15:09 Uhr
@S.Lott Ich vermute, Sie sollten das Kapitel “Hintergrund und Geschichte” aus Ihrem Python-Buch entfernen.
– Johannes Schaub – litb
11. März 2010 um 15:13 Uhr
@S.Lott Wo ist meine -1? Bleiben Sie wenigstens bei Ihrer Bissigkeit.
– xyz
11. März 2010 um 15:17 Uhr
@S.Lott – Es löst möglicherweise kein bestimmtes Problem im Augenblickaber ich habe festgestellt, dass das Verständnis der Designentscheidungen mir normalerweise geholfen hat, ein viel besseres Verständnis einer Sprache zu erlangen.
– Edan Maor
11. März 2010 um 15:17 Uhr
Norman Ramsey
Wenn Sie ein wenig Zeit in der Bibliothek verbringen, müssen Sie nicht spekulieren. Hier sind einige Aussagen entnommen Dennis Ritchies Artikel über die Evolution von C. Der Kontext ist, dass Dennis auf Ken Thompsons Sprache B aufbaut, die auf dem sehr winzigen PDP-7, einer wortadressierten Maschine, implementiert wurde. Aufgrund des wachsenden Interesses bekam die Gruppe einen der allerersten PDP-11. Dennis schreibt,
Das Aufkommen des PDP-11 deckte mehrere Unzulänglichkeiten des semantischen Modells von B auf. Erstens waren seine Zeichenbehandlungsmechanismen, die mit wenigen Änderungen von BCPL geerbt wurden, ungeschickt: Die Verwendung von Bibliotheksprozeduren, um gepackte Zeichenfolgen in einzelne Zellen zu verteilen und dann neu zu packen, oder um auf einzelne Zeichen zuzugreifen und sie zu ersetzen, fing an, sich umständlich, sogar albern, anzufühlen byteorientierte Maschine.
Das B- und BCPL-Modell implizierte einen Overhead beim Umgang mit Zeigern: Die Sprachregeln erzwangen durch die Definition eines Zeigers als Index in einem Array von Wörtern die Darstellung von Zeigern als Wortindizes. Jede Zeigerreferenz erzeugte eine Laufzeitskalenumwandlung von dem Zeiger zu der von der Hardware erwarteten Byteadresse.
Aus all diesen Gründen schien ein Typisierungsschema notwendig zu sein, um mit der Zeichen- und Byte-Adressierung fertig zu werden und um sich auf die kommende Gleitkomma-Hardware vorzubereiten. Vor allem andere Themen Typsicherheit und Schnittstellenprüfung schienen damals nicht so wichtig zu sein, wie sie später wurden.
(Hervorhebung von mir.)
Der Aufsatz beschreibt dann Dennis’ Bemühungen, eine neue Zeigersemantik zu erfinden, Arrays zum Laufen zu bringen und sich mit diesem Neumodischen abzufinden struct Idee. Begriffe zur Typsicherheit und zur Unterscheidung von Booleschen Werten von ganzen Zahlen schienen erst viel später wichtig zu sein 🙂
Joey
C ist eigentlich kaum mehr als eine Assemblersprache auf höherer Ebene. Ja, es hat Kontrollstrukturen und so weiter und es hat sogar Typen, die Assembler sicherlich nicht braucht.
Aber die Sprache wurde vor Jahrzehnten entworfen. Und da jedes boolesche Ergebnis auf einzelne Bits im Statuswort des Prozessors herunterfällt, reichte es offensichtlich aus, nur einen ganzzahligen Datentyp dafür zu verwenden. Und es hat den Compiler wahrscheinlich etwas weniger komplex gemacht, da Sie einige Typprüfungen weglassen können (in späteren Sprachen Kontrollstrukturen brauchen ein boolescher Wert, in C brauchen sie nur einen ganzzahligen Wert von entweder 0 oder etwas anderem).
Denken Sie daran, dass auch frühes C verwendet wurde char* Vor void* wurde als generischer Zeigertyp standardisiert. Ein Prozessor hatte keine Ahnung von a void, also verwendete die Sprache den Datenzeiger mit der kleinsten Auflösung, den die Hardware verstand. Mehr “abstrakte” Begriffe wie void* kam später. C ist eine sehr metallene Sprache, und das Abstrahieren von wahr/falsch in einen neuen Datentyp, der etwas nicht widerspiegelt, das Hardware eindeutig verstehen kann, machte nicht viel Sinn (a bool wäre einfach ein char mit zusätzlichen Einschränkungen, einfach genug, um typedef sich selbst, wenn Sie es wirklich brauchen).
– bta
11. März 2010 um 16:04 Uhr
Eine CPU hat keinen “booleschen Typ”, sie arbeitet nur mit Bytes und Vielfachen davon, daher machte ein boolescher Typ zu diesem Zeitpunkt keinen Sinn, da er keinen Vorteil brachte (warum einen Typ verwenden, wenn Sie nur “ist 0” überprüfen können). oder “ist nicht null”)
Sicher, die CPU hat boolesche Typen. Das Flaggenregister ist vollgestopft mit ihnen!
– xtofl
11. März 2010 um 16:59 Uhr
Ja, aber sie sind nicht universell.
– Morfildur
11. März 2010 um 20:28 Uhr
Es war üblich (und ist es in einigen Fällen immer noch), Null als falsch und alle Nicht-Null-Werte als wahr zu behandeln. Das hat Vorteile für die Kurzschrift: zum Beispiel statt while (remaining != 0) kannst du einfach verwenden while (remaining).
Einige Sprachen sind auf das wahre Sein -1 standardisiert. Der Grund dafür ist, dass in der Zweierkomplementnotation (die die meisten Computer verwenden, um negative Zahlen darzustellen) das bitweise Nicht von 0 -1 ist (in 8-Bit-Binär , 11111111 ist dezimal -1).
Im Laufe der Zeit wurde klar, dass die Verwendung einer vom Compiler definierten Konstante eine Menge potenzieller Verwirrung verhindern würde. Es ist schon eine Weile her, seit ich C++ gemacht habe, aber ich bin mir ziemlich sicher, dass jeder Wert ungleich Null immer noch “true” auswerten wird.
Ich vermute, es wurde als ausreichend angesehen, einen ganzzahligen Typ zu haben, wobei 0 falsch und alles, was nicht 0 ist, wahr ist.
Ich denke, das ist die beste Antwort. Die meisten booleschen Werte werden ohnehin als Ganzzahlen behandelt, wenn sie zum Assemblieren kompiliert werden.
– Rob Nicholson
11. März 2010 um 15:16 Uhr
Café
Dem alten C “fehlte” nicht wirklich ein boolescher Typ – es war nur so, dass alle ganzzahligen Typen auch als geeignet angesehen wurden, um doppelte Aufgaben auszuführen und boolesche Werte zu speichern. Dafür sehe ich zwei Hauptgründe:
Prozessoren mit Bitadressierung waren überhaupt nicht üblich (und sind es immer noch nicht), sodass der Compiler nicht wirklich in der Lage wäre, einen “echten booleschen” Typ zu verwenden, um Platz zu sparen – der boolesche Wert wäre immer noch mindestens so groß wie a char sowieso (wenn Sie gehofft haben, effizient darauf zugreifen zu können).
Typen schmaler als int werden erweitert int in Ausdrücken sowieso – also würden die booleschen Operatoren immer noch funktionieren int Operanden.
.. es sieht also so aus, als gäbe es keinen überzeugenden Fall, dass ein dedizierter boolescher Typ tatsächlich praktische Vorteile bringen würde.
Denken Sie daran, dass die C-Sprache eine Reihe von Operatoren hat, die boolesche Ergebnisse erzeugen (entweder als 0 oder 1 definiert) – !, &&, ||, !=, ==, <, <=, > und >= – es ist also nur ein dedizierter boolescher Typ, der nicht vorhanden ist.
Ich denke, das ist die beste Antwort. Die meisten booleschen Werte werden ohnehin als Ganzzahlen behandelt, wenn sie zum Assemblieren kompiliert werden.
– Rob Nicholson
11. März 2010 um 15:16 Uhr
Der Typ, den Sie zum Speichern eines booleschen Werts verwenden, verkörpert (normalerweise) einen Kompromiss zwischen Raum und Zeit. Normalerweise erhalten Sie die schnellsten Ergebnisse (zumindest für eine einzelne Operation), indem Sie ein int (normalerweise vier Bytes) verwenden. Wenn Sie andererseits sehr viele verwenden, kann es viel sinnvoller sein, ein Byte zu verwenden oder sie sogar so zu packen, dass jeder Wert, den Sie speichern, nur ein einziges Bit verwendet – aber wenn/falls Sie das tun, das Lesen oder Schreiben eines einzelnen Bits wird wesentlich teurer (und erfordert zusätzlichen Code).
Da es keine Antwort gab, die wirklich „richtig“ war, überließen sie die Entscheidung dem Benutzer, basierend auf den Anforderungen des Programms, das er schrieb.
Die eigentliche Frage ist also, warum in C99 ein boolescher Typ hinzugefügt wurde. Meine Vermutung ist, dass ein paar Faktoren eine Rolle spielen. Erstens erkannten sie, dass Lesbarkeit und Benutzerfreundlichkeit für den Programmierer heute normalerweise wichtiger sind, als die absolut bestmögliche Leistung zu erbringen. Zweitens führen Compiler jetzt viel mehr globale Analysen durch, sodass es zumindest möglich ist, jemanden zu erraten könnte Schreiben Sie einen Compiler, der versucht, eine Darstellung auszuwählen, die für ein bestimmtes Programm am besten geeignet ist (obwohl ich keinen kenne, der das wirklich tut).
+1: Mir hat die Erwähnung des Raum-Zeit-Kompromisses gefallen. Das ist ein sehr wichtiger Punkt.
– Arun
12. März 2010 um 5:52 Uhr
Bei manchen Compilern ist an int ist das schnellste Format zum Speichern eines booleschen Werts. Auf vielen (aber nicht allen) jedoch a char wäre genauso schnell. Einige Embedded-System-Prozessoren haben eine Besonderheit bit Typ, der noch schneller ist (obwohl solche Prozessoren im Allgemeinen nicht zulassen, dass man ihn einschließt bit Typen innerhalb anderer Strukturen). Es wäre dumm, einen booleschen Wert in einem zu speichern int auf einer Plattform, wo a char wäre genauso schnell (oder für einige eingebettete Prozessoren sogar noch schneller).
– Superkatze
11. Juni 2012 um 17:33 Uhr
Was Supercat auch sagte, das anfängliche Ziel für c waren im Allgemeinen sehr speicherbegrenzte Maschinen, Sie würden es fast immer vorziehen, Ihr Bit-Packing manuell zu verwalten. Das Hinzufügen eines booleschen Typs damals hätte das gefördert, was damals als schreckliche Maschinencodeausgabe angesehen worden wäre.
– Bill K
23. Oktober 2017 um 23:35 Uhr
@supercat Es gibt immer noch eine geringfügige Codegröße/Leistungseinbuße _Boolist vorbei chars oder ints als ganzzahlige Daten, bei denen es bisher egal war, ob es sich um 1 oder 432 oder einen anderen Wert ungleich 0 handelte, müssen jetzt in beide normalisiert werden 0 oder 1zumindest wo beobachtbar.
– PSkočik
18. März 2019 um 12:20 Uhr
Ich würde hinzufügen, dass das Love/Hate-Stiefkind C++ bereits einen dedizierten booleschen Typ hatte, und das Hinzufügen war gut für die Zusammenarbeit.
– Deduplizierer
30. Mai 2020 um 18:07 Uhr
14038600cookie-checkWarum hatte C vor C99 keinen booleschen Datentyp?yes
-1: Welches Problem wird durch die Kenntnis der Implementierungsdetails von Kernighan und Ritchie in C gelöst?
– S. Lott
11. März 2010 um 15:07 Uhr
@S.Lott – Entschuldigung, habe ich den Zweck von StackOverflow nicht verstanden? Ist diese Frage nicht programmierbezogen? Aus den FAQ: “Dies ist ein Ort für Fragen, die beantwortet werden können.” “Solange Ihre Frage … detailliert und spezifisch ist, klar und einfach geschrieben ist und für mindestens einen anderen Programmierer irgendwo von Interesse ist.” Was habe ich noch verpasst?
– Andy Shellam
11. März 2010 um 15:09 Uhr
@S.Lott Ich vermute, Sie sollten das Kapitel “Hintergrund und Geschichte” aus Ihrem Python-Buch entfernen.
– Johannes Schaub – litb
11. März 2010 um 15:13 Uhr
@S.Lott Wo ist meine -1? Bleiben Sie wenigstens bei Ihrer Bissigkeit.
– xyz
11. März 2010 um 15:17 Uhr
@S.Lott – Es löst möglicherweise kein bestimmtes Problem im Augenblickaber ich habe festgestellt, dass das Verständnis der Designentscheidungen mir normalerweise geholfen hat, ein viel besseres Verständnis einer Sprache zu erlangen.
– Edan Maor
11. März 2010 um 15:17 Uhr