wo expr auszuwerten und dem Ergebnis zuzuordnen a iff a ist nicht eingestellt. dies beruht auf den Kurzschlussfähigkeiten des logischen ODER.
Der kürzere Weg, das Obige zu schreiben, wäre natürlich
a ||= expr;
aber (zu meiner Überraschung) hat C keine logischen Zuweisungsoperatoren.
Meine Frage ist also zweigeteilt. Erstens, gibt es einen kürzeren Weg, um die erste Anweisung in Standard-C zu schreiben (der ternäre Operator ist noch schlimmer – a = a ? a : expr erfordert, dass ich buchstabiere a dreimal).
Zweitens, warum gibt es in C keine logischen Zuweisungen? Mögliche Gründe, die mir einfallen, sind:
es macht die Grammatik schwieriger zu analysieren?
Gibt es eine gewisse Subtilität bei der Handhabung von Kurzschlüssen für diese Fälle?
es wurde als überflüssig angesehen (aber ist das nicht ein Argument gegen ALLE Operatorzuweisungen?)
BEARBEITEN
Bitte entsperren Sie diese Frage, weil:
Die Frage, mit der es verknüpft wurde (als angebliches Duplikat von), WURDE NICHT BEANTWORTET. Die (akzeptierte) Antwort auf diese Frage besagt dies ||= ist nicht vorhanden, da die Funktionalität von dupliziert wird |=. Das ist die falsche Antwort. |= schließt nicht kurz.
C und C++ sind NICHT die gleichen Sprachen. Ich möchte wissen, warum C es nicht hat. Tatsächlich macht die Tatsache, dass abgeleitete Sprachen wie C ++ und insbesondere Java (die nicht unter den Problemen von Legacy-Code litten, wie in Edmunds Antwort vorgeschlagen wurde) die Frage noch interessanter.
BEARBEITEN 2
Es scheint jetzt, als wäre meine ursprüngliche Absicht falsch gewesen. In der Aussage a = a || expr (wo a ist ganzzahlig und expr gibt einen ganzzahligen Wert zurück, zuerst beide a und expr wird implizit in “booleans” konvertiert und dann wird der “boolean”-Wert zugewiesen a. Dies ist falsch – der integrale Wert geht verloren. Danke, Jens und Edmund.
Also für den ersten Teil der Frage, die richtigen Wege, nicht Alternativen :), meine Absicht zu codieren wäre:
if (!a) a = expr;
oder
a = a ? a : expr;
Sie sollten gleich optimiert werden (glaube ich), obwohl ich persönlich die erste bevorzugen würde (weil sie eine weniger hat a tippen).
Der zweite Teil der Frage bleibt jedoch bestehen. Die Argumente, die Jens und Edmund über die Mehrdeutigkeit in a ||= expr gleich gut anwenden a = a || expr. der Zuordnungsfall kann einfach wie der normale behandelt werden:
Konvertieren a zu boolesch
wenn es wahr ist, wird der Wert des gesamten Ausdrucks gleich dem booleschen Wert von a
ansonsten auswerten exprErgebnis in booleschen Wert umwandeln, zuweisen zu aund schicke es zurück
Die obigen Schritte scheinen für die Zuweisung und den Normalfall gleich zu sein.
Diese Frage ist nicht ein exaktes Duplikat des oben erwähnten “möglichen Duplikats”. Diese Frage fragt, warum es keine syntaktische Abkürzung für gibt ||=usw. Diese Frage fragt, warum C den Trick nicht zulässt, nicht-boolesche Werte durch einen booleschen Operator zu übertragen.
– Edmund
17. August 2010 um 9:41 Uhr
Ich wollte eine Antwort posten: Es wäre schön, wenn diese mit Kurzschließen arbeiten würden. Es gibt die Möglichkeit if ( ! a ) a = expr; das ist ziemlich klar und prägnant. Was die Tricks betrifft, beachten Sie, dass die Addition und Multiplikation von Booleschen ODER- bzw. UND-Funktionen erzeugt, solange Sie keine Kurzschlüsse oder eine Umwandlung benötigen bool, += und *= durchführen wie ||= und &&= beziehungsweise.
– Kartoffelklatsche
17. August 2010 um 9:43 Uhr
Da dies vorzeitig geschlossen wird antworte ich in einem Kommentar. Ich denke, das existiert nicht, weil seine Interpretation mehrdeutig wäre. Welcher Wert soll in zugewiesen werden a |= expr das Ergebnis von expr oder sein logischer Wert? Was soll das für ein Typ sein a |= expr als Ganzes, intdie Art von a oder das Ergebnis der Förderung a und expr? Ich glaube nicht, dass es eine direkte Lösung für diese Frage gibt, und wahrscheinlich hat deshalb jeder, der darüber nachgedacht hat, schnell aufgegeben. Ich persönlich würde gehen a = (a ? a : expr) und lassen Sie den Compiler die Zuweisung optimieren.
– Jens Gustedt
17. August 2010 um 12:44 Uhr
Ich denke, es gibt auch ein Argument dafür, dass a &&= und ||= Operator würde ein neues semantisches Konzept in die Sprache einführen, die bedingte Zuweisung. Das ternäre als lvalue ist in einigen Compilern schon schlimm genug, brauchen Sie nicht mehr hinzuzufügen.
– Patrick Schlüter
17. August 2010 um 16:45 Uhr
Es gibt eine GCC-Erweiterung a ?: b was bedeutet a ? a : b aber ohne die extra Auswertung
– MM
16. April 2014 um 14:13 Uhr
Chux – Wiedereinsetzung von Monica
a ||= expr ist aufgrund der Kurzschlussauswertung seines Äquivalents problematisch a = a || expr.
Haben a ||= expr funktionieren wie a = a || expr Betrachten Sie die Behauptung von OP:
„In der Erklärung a = a || expr …, zuerst werden sowohl a als auch expr implizit in “booleans” umgewandelt,
Das ist nicht ganz richtig. expr wird nicht konvertiert, wenn a wertet zu true. Dies würde einen Unterschied machen sollten expr etwas sein wie scanf() oder rand() oder eine Funktion, die den Status des Programms beeinflusst hat.
Code wie a ||= scanf("%d", &i) != 1; würde nur versuchen, Daten mit einem falschen Wert einzuscannen a. Obwohl es möglich wäre, die Sprache auf diese Weise zu erweitern, schließen zusätzliche Operatoren den aktuellen Satz von kurz || und && würde wahrscheinlich mehr Codierungsprobleme verursachen als klare Vereinfachungen.
Andererseits: Eine schnelle, wenn auch verschleierte Möglichkeit, Code zu schreiben, bei dem Funktionen im Fehlerfall Nicht-Null-Codes zurückgeben.
// Perform functions until an error occurs.
bool error = foo1();
error &&= foo2(); // Only valid if C was extended with &&=
error &&= foo3();
Jan Hudec
Weil der Rückgabetyp von Operatoren || und && ist nicht derselbe Typ wie ihr linkes Argument.
Der Rückgabetyp von || und && ist immer int1, während das linke Argument ein ganzzahliger, Gleitkomma- oder Zeigertyp sein kann. Die Operanden müssen auch nicht vom gleichen Typ sein. Daher definieren x ||= y wie x = x || y und x &&= y wie x = x && y wie es mit anderen erweiterten Zuweisungen konsistent wäre, das Ergebnis für die meisten Typen nicht im Argument speichern könnte.
Sie könnten andere Definitionen finden, z x ||= y wie if(!x) x = y und x &&= y wie if(!y) x = yaber das wäre nicht ganz offensichtlich und ist es auch nicht das nützlich, also war es nicht enthalten.
1In C++ ist es bool.
Ich denke, die einfache Antwort lautet: || ist ein boolescher Operator: und in C ist ein “boolean” 0 oder 1. Die Operanden werden implizit in boolesche Werte konvertiert (ich habe nicht überprüft, ob die Spezifikation das tatsächlich sagt, aber C verhält sich so), und das Ergebnis ist a boolesch.
Die Semantik zu ändern, um dieses Muster zu unterstützen, kann durchaus machbar sein – bis sich jemand darauf verlässt || tun, was es immer getan hat.
Es gibt kein boolean Geben Sie C ein, damit Operanden nicht konvertiert werden boolean und Ergebnis von || und ‘&&’ ist es nicht boolean.
– qrdl
17. August 2010 um 10:08 Uhr
@qrdl Da hast du recht boolean (obwohl C99 hat _Bool), aber &&, || (und !) sind so definiert, dass sie entweder 0 oder 1 ergeben. Siehe C99-Standard §6.5.13 und §6.5.14.
– schott
17. August 2010 um 10:47 Uhr
Vielen Dank. Meine Verwendung von “Anführungszeichen” zeigt an, dass dies die ungefähre Bedeutung ist. Wenn ich mich auf das Mythische beziehen würde boolean Typ hätte ich es als solches angegeben. Meine Antwort als Ganzes bezieht sich auf das Verhalten, nicht auf die abstrakte Spezifikation.
– Edmund
17. August 2010 um 10:59 Uhr
Detail: “und das Ergebnis ist ein boolescher Wert.” –> Ergebnis ist Typ int mit einem booleschen Wert von 0 oder 1.
– chux – Wiedereinsetzung von Monica
22. April 2021 um 1:22 Uhr
Ich kann keinen bestimmten Grund finden, warum die Operatoren nicht existieren (in C99).
Der einzige Grund, den ich finden kann, ist, dass es in C89 keinen booleschen Typ gab und diese booleschen Operatoren ausschließlich für die Verwendung gedacht waren if‘s.
Beispiel:
int i = 5;
/* This should not make any difference,
since or'ing with false, shouldn't change
the value... dib di dib diddy...*/
i ||= 0; /* Actually: i = i || 0, which gives 'true' */
i ist jetzt ‘1’, was für die meisten Menschen ziemlich kontraintuitiv ist.
Dieser Operator bringt ohne den booleschen Typ offensichtlich keine Klarheit oder Codierungsverbesserung, das würde Sinn machen, wenn er mit einem anderen or’d wäre.
Meiner Meinung nach ist die Umsetzung von a ||= b; wie if(!a) a = b; wäre ziemlich einfach und wurde bereits von zB Lua implementiert.
Ihre Frage scheint also ein bisschen zu sein, warum C so entworfen wurde, wie es entworfen wurde. Wenn es bei dieser Frage um C++ ginge, könntest du zum Beispiel Bjarne Stroustrup fragen und ihn fragen, was in ihn gefahren ist. Da dies nicht der Fall ist, scheint mir dies eine Art Sackgasse zu sein, da der Standard schon seit geraumer Zeit geschrieben wurde und man die Leute nicht mehr wirklich fragen kann, warum der H***.
Andererseits hätte dieser unvollständige Operatorsatz (meiner Meinung nach) schon mit einer ähnlichen Notation wie Ihrer komplettiert werden müssen, da meiner Meinung nach kein Grund dagegen spricht.
Ich hoffe, ich konnte ein wenig helfen.
Eine einfache Erklärung ist diese.
bool resultsComputeAll = false;
bool resultsUntilFirst = false;
for (int i = 0; i < 10; ++i) {
resultsComputeAll = compute(i) || resultsComputeAll;
resultsUntilFirst = resultsUntilFirst || compute(i);
}
Welches wäre result ||= compute(i)? Es ist mehrdeutig, also ist es besser, es nicht zu definieren.
14016500cookie-checkWarum hat C keinen logischen Zuweisungsoperator?yes
Diese Frage ist nicht ein exaktes Duplikat des oben erwähnten “möglichen Duplikats”. Diese Frage fragt, warum es keine syntaktische Abkürzung für gibt
||=
usw. Diese Frage fragt, warum C den Trick nicht zulässt, nicht-boolesche Werte durch einen booleschen Operator zu übertragen.– Edmund
17. August 2010 um 9:41 Uhr
Ich wollte eine Antwort posten: Es wäre schön, wenn diese mit Kurzschließen arbeiten würden. Es gibt die Möglichkeit
if ( ! a ) a = expr;
das ist ziemlich klar und prägnant. Was die Tricks betrifft, beachten Sie, dass die Addition und Multiplikation von Booleschen ODER- bzw. UND-Funktionen erzeugt, solange Sie keine Kurzschlüsse oder eine Umwandlung benötigenbool
,+=
und*=
durchführen wie||=
und&&=
beziehungsweise.– Kartoffelklatsche
17. August 2010 um 9:43 Uhr
Da dies vorzeitig geschlossen wird antworte ich in einem Kommentar. Ich denke, das existiert nicht, weil seine Interpretation mehrdeutig wäre. Welcher Wert soll in zugewiesen werden
a |= expr
das Ergebnis vonexpr
oder sein logischer Wert? Was soll das für ein Typ seina |= expr
als Ganzes,int
die Art vona
oder das Ergebnis der Förderunga
undexpr
? Ich glaube nicht, dass es eine direkte Lösung für diese Frage gibt, und wahrscheinlich hat deshalb jeder, der darüber nachgedacht hat, schnell aufgegeben. Ich persönlich würde gehena = (a ? a : expr)
und lassen Sie den Compiler die Zuweisung optimieren.– Jens Gustedt
17. August 2010 um 12:44 Uhr
Ich denke, es gibt auch ein Argument dafür, dass a
&&=
und||=
Operator würde ein neues semantisches Konzept in die Sprache einführen, die bedingte Zuweisung. Das ternäre alslvalue
ist in einigen Compilern schon schlimm genug, brauchen Sie nicht mehr hinzuzufügen.– Patrick Schlüter
17. August 2010 um 16:45 Uhr
Es gibt eine GCC-Erweiterung
a ?: b
was bedeuteta ? a : b
aber ohne die extra Auswertung– MM
16. April 2014 um 14:13 Uhr