Warum unterstützt der Boolesche Typ in C ++ ++, aber nicht -?

29

Warum --existiert der Operator nicht für bool, wohingegen er für operator existiert ++?

Ich habe es in C ++ versucht und weiß nicht, ob meine Frage auf eine andere Sprache zutrifft. Ich werde es auch gerne wissen.

Ich weiß , ich kann den Operator ++mit einem Bool verwenden. Es macht jeden Bool gleich wahr.

bool b = false;
b++;
// Now b == true.

Warum können wir den Operator nicht anders verwenden --?

bool b = true;
b--;
// Now b == false;

Es ist nicht sehr nützlich, aber ich bin neugierig.

aloisdg sagt Reinstate Monica
quelle
8
Diese Frage zu StackOverflow ist möglicherweise aufschlussreich.
Blrfl
Also Grund zur Geschichte. Vielen Dank für den Link. Kannst du eine Antwort schreiben und ich setze sie als gelöst?
aloisdg sagt Reinstate Monica
Links alleine geben keine guten Antworten, und es gibt keinen guten Mechanismus, um diese Frage als Duplikat von etwas auf einer anderen SE-Site zu kennzeichnen.
Blrfl
1
Also sollten wir ein Thema in meta.stackexchange.com oder so öffnen. Ich denke, du solltest etwas Karma für die gute Verbindung bekommen, und wenn dich jemand positiv bewertet, sollte der Autor der ursprünglichen Antwort etwas Karma bekommen. Tatsächlich sollte die ursprüngliche Frage auch etwas Karma bekommen.
Aloisdg sagt Reinstate Monica
2
@aloisdg Cross Site Dups sind ein altes Problem bei MSO. Verfolgen Sie die verknüpften Fragen , um eine umfassendere Ansicht zu erhalten.

Antworten:

53

In den alten Tagen von C gab es keinen Booleschen Typ. Die Leute verwendeten die intzum Speichern von Booleschen Daten, und es funktionierte meistens. Null war falsch und alles andere war wahr.

Dies bedeutet, wenn Sie eine nehmen int flag = 0;und später tun flag++, wäre der Wert wahr. Dies würde funktionieren, unabhängig davon, wie hoch der Wert von flag war (es sei denn, Sie haben es häufig getan, es hat sich gedreht und Sie sind auf Null zurückgekehrt, aber ignorieren wir das) - Erhöhen des Flags, wenn sein Wert 1 war, würde 2 ergeben, was immer noch war wahr.

Einige Leute benutzten dies, um einen booleschen Wert bedingungslos auf true zu setzen. Ich bin nicht sicher, ob es jemals idiomatisch wurde , aber es ist in irgendeinem Code.

Dies hat nie funktioniert --, denn wenn der Wert nicht 1 ist (was auch immer sein könnte), ist der Wert immer noch nicht falsch. Und wenn es bereits false ( 0) war und Sie einen Dekrementierungsoperator dafür durchgeführt haben, würde es nicht false bleiben.

Bei der Verlagerung von Code von C nach C ++ in den Anfängen war es sehr wichtig, dass der in C ++ enthaltene C-Code weiterhin funktioniert. Und so heißt es in der Spezifikation für C ++ (Abschnitt 5.2.6 (auf Seite 71)):

Der durch Anwenden eines Postfix ++ erhaltene Wert ist der Wert, den der Operand vor dem Anwenden des Operators hatte. [Anmerkung: Der erhaltene Wert ist eine Kopie des ursprünglichen Werts.] Der Operand muss ein veränderbarer Wert sein. Der Typ des Operanden muss ein arithmetischer Typ oder ein Zeiger auf einen vollständigen Objekttyp sein. Nachdem das Ergebnis notiert wurde, wird der Wert des Objekts durch Hinzufügen von 1 geändert, sofern es sich nicht um ein Objekt vom Typ boolhandelt. In diesem Fall wird der Wert auf true festgelegt. [Hinweis: Diese Verwendung ist veraltet, siehe Anhang D.]

Der Operand von postfix - wird analog zum Operator postfix ++ dekrementiert, nur dass der Operand nicht vom Typ sein soll bool.

Dies wird erneut in Abschnitt 5.3.2 erwähnt (für den Präfix-Operator - 5.2.6 war auf Postfix).

Wie Sie sehen, ist dies veraltet (Anhang D im Dokument, Seite 709) und sollte nicht verwendet werden.

Aber deshalb. Und manchmal können Sie den Code sehen. Aber tu es nicht.

Gemeinschaft
quelle
5
"Einige Leute haben dies verwendet, um einen booleschen Wert bedingungslos auf true zu setzen." Nennen wir sie verdammte Dummköpfe, keine Menschen.
Deduplizierer
@ Deduplicator: Vielleicht war es eine Frage der Leistung: Das Laden eines Werts in eine Variable hat möglicherweise mehr Prozessorzyklen in Anspruch genommen als das Inkrementieren der Variablen. Natürlich spielt dies bei modernen Computern wahrscheinlich keine Rolle.
Giorgio
1
@Giorgio das ist ziemlich wahrscheinlich. Denken Sie daran, dass C so geschrieben wurde, dass es eng mit dem PDP-7-Befehlssatz übereinstimmt, und dass der PDP-11 andere Verbesserungen aufwies. Daraus folgt : "Die Leute vermuten oft, dass sie dafür geschaffen wurden, die vom DEC PDP-11 bereitgestellten Adressmodi für automatisches Inkrementieren und automatisches Dekrementieren zu verwenden, auf denen C und Unix zum ersten Mal populär wurden. Dies ist historisch unmöglich, da es keinen PDP-Modus gab. Der PDP-7 hatte jedoch einige "Auto-Inkrement" -Speicherzellen mit der Eigenschaft, dass eine indirekte Speicherreferenz durch sie die Zelle inkrementierte. "
@Deduplicator: In Code, der Ganzzahlen für Boolesche Werte verwendet, kann eine Variable, die für jeden ... was auch immer ... inkrementiert wird, sowohl als Zähler (wie oft er inkrementiert wurde) als auch als Boolescher Wert (wurde er überhaupt inkrementiert oder) fungieren nicht).
Keith Thompson
2

Teilweise Bewältigung von Legacy-Code, der intals Boolescher Typ verwendet wird.

Mike Graham
quelle
1
Meine Frage ist ein Duplikat von hier stackoverflow.com/questions/3450420/… . Übrigens, danke für deine Antwort.
Aloisdg sagt Reinstate Monica
1

Um die historische Bedeutung dieser Frage zu verstehen, müssen Sie den Fall des Therac-25 betrachten. Der Therac-25 war ein medizinisches Gerät, das Krebspatienten mit Strahlung versorgte. Es wurde von schlechten Programmierpraktiken geplagt, die zu seiner schlechten Sicherheitsbilanz beitrugen (mit mehreren Todesfällen, die darauf zurückgeführt wurden).

http://courses.cs.vt.edu/professionalism/Therac_25/Therac_1.html

(gehe zum Ende von Seite 3)

Bei jedem Durchlauf der Setup-Test-Routine wird die obere Kollimatorpositionsprüfung inkrementiert, eine gemeinsam genutzte Variable mit der Bezeichnung Class3. Wenn Class3 ungleich Null ist, liegt eine Inkonsistenz vor und die Behandlung sollte nicht fortgesetzt werden. Ein Nullwert für Klasse 3 zeigt an, dass die relevanten Parameter mit der Behandlung übereinstimmen und der Strahl nicht gesperrt ist.

...

Während des Maschinen-Setups wird der Setup-Test mehrere hundert Mal ausgeführt, da er sich selbst neu terminiert und darauf wartet, dass andere Ereignisse eintreten. Im Code wird die Variable Class3 in jedem Durchgang durch den Setup-Test um eins erhöht. Da die Class3-Variable 1 Byte ist, kann sie nur einen Maximalwert von 255 Dezimalstellen enthalten. Daher läuft die Variable bei jedem 256. Durchlauf des Setup-Test-Codes über und hat den Wert Null. Dies bedeutet, dass bei jedem 256. Durchgang des Einstelltests der obere Kollimator nicht überprüft und ein Fehler des oberen Kollimators nicht erkannt wird. Die Überbelichtung trat auf, als der Bediener genau in dem Moment auf die Schaltfläche "Setzen" drückte, in dem Class3 auf Null überging. Daher wurde Chkcol nicht ausgeführt, und F $ mal wurde nicht eingestellt, um anzuzeigen, dass sich der obere Kollimator noch in Feldlichtposition befand. Die Software schaltete die vollen 25 MeV ein, ohne dass das Ziel vorhanden war und ohne dass gescannt wurde. Es resultierte ein hochkonzentrierter Elektronenstrahl, der vom im Weg befindlichen Edelstahlspiegel gestreut und abgelenkt wurde.

Der Therac-25 verwendete so etwas wie operator++einen bool. Die von ihnen verwendete Programmiersprache war jedoch nicht C ++, und ihr Datentyp war nicht C ++ bool. Im Gegensatz zur Garantie in C ++ bleibt ein regulärer Integer-Typ jedoch einfach bestehen. Ihr Datentyp war das Äquivalent von uint8_t.

C ++ hat beschlossen, die operator++Umgebung für Programmierer wie diese zu behalten , aber anstatt den Wert zu erhöhen, wird er einfach so eingestellt true, dass solche Dinge vermieden werden.

Beachten Sie, dass dies operator++(bool)veraltet ist.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf

Anhang D von C ++ 14:

D.1 Inkrementoperator mit dem Operanden bool
Die Verwendung eines Operanden vom Typ bool mit dem Operator ++ ist veraltet (siehe 5.3.2 und 5.2.6).

David Stone
quelle
Während dies erklären würde, warum es veraltet ist, erklärt es nicht, warum es überhaupt existiert.
Es existiert, weil es einige Leute gab, die einen Booleschen Wert durch Inkrementieren beim Programmieren in C festlegten. C ++ wurde entwickelt, um den Übergang von C zu vereinfachen, daher unterstützten sie ihn mit dem boolTyp. Ich habe nur versucht, ein historisches Beispiel dafür zu geben, wann die Leute tatsächlich so programmiert haben.
David Stone