(Ja, ich weiß, das ist einfach zu testen – nur hier dokumentieren, damit jemand schnell die Antwort findet.)
Aktualisieren: Diese Frage hat eine Nuance bei der Verwendung des Komma-Operators aufgedeckt. Nur um das zu dokumentieren:
a = b, c; // a is set to the value of b!
a = (b, c); // a is set to the value of c!
Diese Frage wurde tatsächlich von einem Tippfehler im Code inspiriert. Was sein sollte
a = b;
c = d;
Wurde zu
a = b, // <- Note comma typo!
c = d;
Lesen Sie hier mehr darüber. stackoverflow.com/questions/12824378/…
– Coding-Mash
14. Dezember 2012 um 15:54 Uhr
Mögliches Duplikat von Was macht der Kommaoperator `,` in C?. Es hat dich um einen Tag geschlagen. Und die Antwort von lillq liefert eine Antwort auf die Frage nach a = (b, c);.
– jww
8. Mai 2015 um 23:33 Uhr
Aber in diesem Fall a = b, c = d; tut tatsächlich das gleiche wie beabsichtigt a = b; c = d;?
– Bondolin
11. November 2015 um 19:52 Uhr
@NargothBond Nicht unbedingt. Wenn b und d sind Funktionsauswertungen, die einen gemeinsamen Zustand verwenden (und modifizieren), wird die Ausführungsreihenfolge erst definiert C++17.
– Nylon
9. September 2018 um 16:38 Uhr
Konrad Rudolf
Beachten Sie, dass der Kommaoperator in C++ möglicherweise überladen wird. Das tatsächliche Verhalten kann daher stark von dem erwarteten abweichen.
Als Beispiel, Boost.Spirit verwendet den Kommaoperator recht geschickt, um Listeninitialisierer für Symboltabellen zu implementieren. Dadurch wird folgende Syntax möglich und sinnvoll:
keywords = "and", "or", "not", "xor";
Beachten Sie, dass der Code aufgrund der Operatorpriorität (absichtlich!) identisch mit ist
(((keywords = "and"), "or"), "not"), "xor";
Das heißt, der erste aufgerufene Operator ist keywords.operator =("and") die ein Proxy-Objekt zurückgibt, auf dem die verbleibenden operator,s werden aufgerufen:
Ähm, Sie können die Priorität jedoch nicht ändern, was bedeutet, dass Sie Ihre Liste wahrscheinlich in Klammern setzen sollten.
– Jeff Burdges
8. Oktober 2011 um 18:56 Uhr
@ Jeff Im Gegenteil. Mit einer Klammer um die Liste würde dies nicht funktionieren, da der Compiler dann nur den Komma-Operator zwischen zwei sieht char[], die nicht überladen werden kann. Der Code absichtlich ruft zuerst die an operator= und dann anschließend operator, für jedes verbleibende Element.
– Konrad Rudolf
9. Oktober 2011 um 11:04 Uhr
Der Kommaoperator hat die am niedrigsten Vorrang aller C/C++-Operatoren. Daher ist es immer das letzte, das an einen Ausdruck gebunden wird, was Folgendes bedeutet:
a = b, c;
ist äquivalent zu:
(a = b), c;
Eine weitere interessante Tatsache ist, dass der Kommaoperator a einleitet Sequenzpunkt. Das bedeutet, dass der Ausdruck:
a+b, c(), d
hat garantiert seine drei Unterausdrücke (a+b, C() und D) der Reihe nach ausgewertet. Dies ist von Bedeutung, wenn sie Nebenwirkungen haben. Normalerweise dürfen Compiler Unterausdrücke in beliebiger Reihenfolge auswerten, die sie für richtig halten. zum Beispiel in einem Funktionsaufruf:
someFunc(arg1, arg2, arg3)
Argumente können in beliebiger Reihenfolge ausgewertet werden. Beachten Sie, dass die Kommas im Funktionsaufruf sind nicht Operatoren; Sie sind Trennzeichen.
Es lohnt sich, darauf hinzuweisen , hat einen so geringen Vorrang, dass es sogar hinterherhinkt selbst 😉 …das heißt: comma-as-Operator hat einen niedrigeren Vorrang als comma-as-Separator. Also, wenn Sie Komma-als-Operator innerhalb eines einzelnen Funktionsarguments, einer Variablenzuweisung oder eines anderen Komma-getrennt Liste – dann müssen Sie Klammern verwenden, zB: int a = 1, b = 2, weirdVariable = (++a, b), d = 4;
– Unterstrich_d
16. April 2016 um 21:45 Uhr
Leon Timmermans
Es wäre gleich b.
Der Kommaoperator hat eine niedrigere Priorität als die Zuweisung.
CygnusX1
Der Kommaoperator:
hat den niedrigsten Vorrang
ist linksassoziativ
Eine Standardversion des Kommaoperators ist für alle Typen (integriert und benutzerdefiniert) definiert und funktioniert wie folgt – angegeben exprA , exprB:
exprA ausgewertet wird
das Ergebnis von exprA wird ignoriert
exprB ausgewertet wird
das Ergebnis von exprB wird als Ergebnis des gesamten Ausdrucks zurückgegeben
Bei den meisten Operatoren darf der Compiler die Reihenfolge der Ausführung wählen und es ist sogar erforderlich, die Ausführung überhaupt zu überspringen, wenn dies das Endergebnis nicht beeinflusst (z false && foo() wird den Anruf überspringen foo). Dies ist jedoch beim Kommaoperator nicht der Fall und die obigen Schritte werden immer ausgeführt*.
In der Praxis funktioniert der standardmäßige Kommaoperator fast genauso wie ein Semikolon. Der Unterschied besteht darin, dass zwei durch ein Semikolon getrennte Ausdrücke zwei separate Anweisungen bilden, während die Komma-Trennung alle als einen einzigen Ausdruck behält. Aus diesem Grund wird der Kommaoperator manchmal in den folgenden Szenarien verwendet:
Die C-Syntax erfordert eine einzelne Ausdruck, keine Stellungnahme. zB hinein if( HERE )
Die C-Syntax erfordert eine einzige Anweisung, nicht mehr, zB bei der Initialisierung der for Schleife for ( HERE ; ; )
Wenn Sie geschweifte Klammern überspringen und eine einzelne Anweisung beibehalten möchten: if (foo) HERE ; (Bitte tu das nicht, es ist wirklich hässlich!)
Wenn eine Anweisung kein Ausdruck ist, kann das Semikolon nicht durch ein Komma ersetzt werden. Unzulässig sind beispielsweise:
(foo, if (foo) bar) (if ist kein Ausdruck)
int x, int y (Variablendeklaration ist kein Ausdruck)
In Ihrem Fall haben wir:
a=b, c;gleichwertig a=b; c;vorausgesetzt, dass a ist ein Typ, der den Kommaoperator nicht überlädt.
a = b, c = d; gleichwertig a=b; c=d;vorausgesetzt, dass a ist ein Typ, der den Kommaoperator nicht überlädt.
Beachten Sie, dass nicht jedes Komma tatsächlich ein Kommaoperator ist. Einige Kommas, die eine ganz andere Bedeutung haben:
int a, b; — Variablendeklarationsliste ist durch Kommas getrennt, aber dies sind keine Kommaoperatoren
int a=5, b=3; — dies ist auch eine kommaseparierte Variablendeklarationsliste
foo(x,y) — Kommagetrennte Argumentliste. In der Tat, x und y kann ausgewertet werden irgendein Befehl!
FOO(x,y) — Kommagetrennte Makroargumentliste
foo<a,b> — durch Komma getrennte Vorlagenargumentliste
int foo(int a, int b) — Kommagetrennte Parameterliste
Foo::Foo() : a(5), b(3) {} — Kommagetrennte Initialisierungsliste in einem Klassenkonstruktor
* Dies trifft nicht ganz zu, wenn Sie Optimierungen anwenden. Wenn der Compiler erkennt, dass ein bestimmter Codeabschnitt absolut keinen Einfluss auf den Rest hat, entfernt er die unnötigen Anweisungen.
Lesen Sie hier mehr darüber. stackoverflow.com/questions/12824378/…
– Coding-Mash
14. Dezember 2012 um 15:54 Uhr
Mögliches Duplikat von Was macht der Kommaoperator `,` in C?. Es hat dich um einen Tag geschlagen. Und die Antwort von lillq liefert eine Antwort auf die Frage nach
a = (b, c);
.– jww
8. Mai 2015 um 23:33 Uhr
Aber in diesem Fall
a = b, c = d;
tut tatsächlich das gleiche wie beabsichtigta = b; c = d;
?– Bondolin
11. November 2015 um 19:52 Uhr
@NargothBond Nicht unbedingt. Wenn
b
undd
sind Funktionsauswertungen, die einen gemeinsamen Zustand verwenden (und modifizieren), wird die Ausführungsreihenfolge erst definiertC++17
.– Nylon
9. September 2018 um 16:38 Uhr