Frage

Wie funktioniert der Kommaoperator in C++?

Wenn ich zum Beispiel Folgendes tue:

a = b, c;  

Entspricht a am Ende b oder c?

(Ja, ich weiß, das ist einfach zu testen – ich dokumentiere es nur hier, damit jemand schnell die Antwort findet.)

Aktualisieren: Diese Frage hat eine Nuance bei der Verwendung des Kommaoperators 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 durch einen Tippfehler im Code inspiriert.Was sein sollte

a = b;
c = d;

Wurde zu

a = b,    //  <-  Note comma typo!
c = d;
War es hilfreich?

Lösung

Es wäre gleich b.

Der Komma-Operator hat eine niedrigere Priorität als Zuordnung.

Andere Tipps

Achten Sie darauf, bemerken, dass der Komma-Operator in C überlastet werden kann ++. Das tatsächliche Verhalten so sehr verschieden von dem sein kann, erwartet.

Als Beispiel Boost.Spirit verwendet den Komma-Operator recht geschickt Liste initializers für Symboltabellen zu implementieren. Somit macht es die folgende Syntax möglich und sinnvoll:

keywords = "and", "or", "not", "xor";

Beachten Sie, dass aufgrund der Rangfolge der Operatoren, der Code ist (absichtlich!) Identisch mit

(((keywords = "and"), "or"), "not"), "xor";

Das heißt, genannt der erste Betreiber ist keywords.operator =("and"), die ein Proxy-Objekt zurückgibt, auf dem die verbleibenden operator,s aufgerufen werden:

keywords.operator =("and").operator ,("or").operator ,("not").operator ,("xor");

Der Komma-Operator hat den niedrigste Vorrang aller C / C ++ Operatoren. Deshalb immer, es ist die letzte zu einem Ausdruck zu binden, diese Bedeutung:

a = b, c;

entspricht:

(a = b), c;

Eine weitere interessante Tatsache ist, dass der Komma-Operator eines Sequenzpunkt einführt. Dies bedeutet, dass der Ausdruck:

a+b, c(), d

ist garantiert seine drei Teilausdrücke haben ( a + b , c () und d ) ausgewertet, um. Dies ist von Bedeutung, wenn sie Nebenwirkungen haben. Normalerweise Compiler dürfen bewerten Teilausdrücke in beliebiger Reihenfolge finden sie fit; zum Beispiel in einem Funktionsaufruf:

someFunc(arg1, arg2, arg3)

Argumente können in einer beliebigen Reihenfolge ausgewertet werden. Beachten Sie, dass die Kommas in dem Funktionsaufruf sind nicht Operatoren; sie sind Separatoren.

Der Komma-Operator:

  • hat die niedrigste Priorität
  • ist linksassoziativ

Eine Standardversion von Komma-Operator ist für alle Arten (integrierte und benutzerdefinierte) definiert, und es funktioniert wie folgt - gegeben exprA , exprB:

  • exprA ausgewertet
  • das Ergebnis exprA ignoriert
  • exprB ausgewertet
  • das Ergebnis exprB wird als Ergebnis des gesamten Ausdrucks zurückgegeben

Bei den meisten Operatoren wird der Compiler die Reihenfolge der Ausführung wählen erlaubt, und es wird auch die Ausführung erforderlich haupt zu überspringen, wenn es nicht das Endergebnis beeinflussen wird (z false && foo() den Anruf überspringen foo). Dies ist jedoch nicht der Fall für Komma-Operator und die obigen Schritte werden immer passieren * .

In der Praxis funktioniert das Standard Komma-Operator fast die gleiche Art und Weise wie ein Semikolon. Der Unterschied besteht darin, dass zwei Ausdrücke, die durch ein Semikolon bildet zwei separate Anweisungen getrennt, während Komma-Trennung alle als einzelnen Ausdruck hält. Aus diesem Grunde Komma-Operator manchmal in den folgenden Szenarien verwendet wird:

  • C-Syntax erfordert einen einzelnen Ausdruck , keine Aussage. z.B. in if( HERE )
  • C-Syntax erfordert eine einzige Anweisung, nicht mehr, z.B. in der Initialisierung der for Schleife for ( HERE ; ; )
  • Wenn Sie eine einzelne Anweisung geschweifte Klammern und halten überspringen wollen: if (foo) HERE ; (! Bitte das nicht tun, es ist wirklich hässlich)

Wenn eine Anweisung nicht ein Ausdruck ist, Semikolon kann nicht durch ein Komma ersetzt werden. Zum Beispiel ist diese nicht zulässig:

  • (foo, if (foo) bar) (if ist kein Ausdruck)
  • x int, int y (Variablendeklaration ist kein Ausdruck)

In Ihrem Fall haben wir:

  • a=b, c;, das entspricht a=b; c;, dass a unter der Annahme des Typs, der nicht den Komma-Operator nicht überlastet werden.
  • a = b, c = d; entspricht a=b; c=d;, dass a unter der Annahme des Typs, der nicht den Komma-Operator nicht überlastet werden.

note Sie, dass jedes Komma nicht eigentlich ein Komma-Operator. Einige Kommas, die eine ganz andere Bedeutung haben:

  • int a, b; --- Variablendeklarationsliste getrennt Komma, aber diese sind nicht Komma Operatoren
  • int a=5, b=3; --- dies ist auch ein Komma Variablendeklarationsliste getrennt
  • foo(x,y) --- kommagetrennte Argumentliste. In der Tat, x und y können ausgewertet werden jeder um!
  • FOO(x,y) --- durch Kommata getrennte Makroargumentliste
  • foo<a,b> --- kommagetrennte Template-Argument-Liste
  • int foo(int a, int b) --- durch Kommata getrennte Parameterliste
  • Foo::Foo() : a(5), b(3) {} --- kommagetrennte Initialisiererliste in einem Klassenkonstruktor

* Das ist nicht ganz richtig, wenn Sie Optimierungen anwenden. Wenn der Compiler erkennt, dass bestimmte Teil des Codes absolut keine Auswirkungen auf den Rest hat, wird es die unnötigen Aussagen entfernen.

Weiterführende Literatur: http://en.wikipedia.org/wiki/Comma_operator

Der Wert von a wird b, aber der Wert von Ausdruck wird c werden. Das heißt, in

d = (a = b, c);

a wäre gleich b und d wäre gleich c.

b der Wert wird auf eine zugewiesen. Nichts wird c passieren

Der Wert von a wird gleich b sein, da der Komma-Operator eine niedrigere Priorität als der Zuweisungsoperator hat.

Ja Komma-Operator hat eine niedrige Priorität als Zuweisungsoperator

#include<stdio.h>
int main()
{
          int i;
          i = (1,2,3);
          printf("i:%d\n",i);
          return 0;
}

Ausgabe: i = 3
Da Komma-Operator immer ganz rechts Wert zurück.
Im Fall des Komma-Operators mit Zuweisungsoperator:

 int main()
{
      int i;
      i = 1,2,3;
      printf("i:%d\n",i);
      return 0;
}

Ouput: i = 1
Da wir Komma-Operator hat niedrigere Priorität als Zuweisung wissen .....

Das Wichtigste zuerst: Comma ist eigentlich kein Operator, für die Compiler es nur ein Token ist, die eine Bedeutung bekommt in Kontext mit anderen Token

.

Was bedeutet das und warum die Mühe machen?

Beispiel 1:

Um den Unterschied zwischen der Bedeutung von dem gleichen Grund in einem anderen Kontext verstehen wir einen Blick auf dieses Beispiel zu nehmen:

class Example {
   Foo<int, char*> ContentA;
}

Normalerweise wird ein C ++ Anfänger würde denken, dass dieser Ausdruck könnte / würde die Dinge vergleichen, aber es ist absolut falsch, die Bedeutung der <, > und , Token depent auf dem Nutzungskontext.

Die richtige Interpretation des obigen Beispiels ist natürlich, dass es sich um eine instatiation einer Vorlage ist.

Beispiel 2:

Wenn wir ein typisch für Schleife mit mehr als einer Initialisierung Größe und / oder mehr als eine Ausdrücke schreiben, die nach jeder Iteration der Schleife erfolgen sollten wir das Komma zu:

for(a=5,b=0;a<42;a++,b--)
   ...

Die Bedeutung des Kommas auf dem Nutzungskontext abhängig ist, hier ist es der Kontext der for Konstruktion.

Was ein Komma in Kontext bedeutet eigentlich?

Um es zu erschweren noch (wie immer in C ++) der Komma-Operator kann sich (dank Konrad Rudolph überlastet für den Hinweis, dass out).

Um wieder auf die Frage zu kommen, der Code

a = b, c;

bedeutet für den Compiler so etwas wie

(a = b), c;

, weil der Priorität des = Token rel="nofollow / Betreiber ist höher als die Priorität des , Token.

und dies ist in Zusammenhang wie

interpretiert
a = b;
c;

(beachten Sie, dass die Interpretation vom Kontext ab, hier ist es weder eine Funktion / Methodenaufruf oder eine Vorlage instatiation.)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top