Was macht der ,
Operator in C?
c
operators
comma-operator
lillq
quelle
quelle
Antworten:
Der Ausdruck:
Zuerst wird Ausdruck1 ausgewertet, dann wird Ausdruck2 ausgewertet und der Wert von Ausdruck2 wird für den gesamten Ausdruck zurückgegeben.
quelle
i
die Werte 5, 4, 3, 2 oder 1 angegeben. Es ist einfach 0. Es ist praktisch nutzlos, es sei denn, die Ausdrücke haben Nebenwirkungen.i = b, c;
ist äquivalent zu(i = b), c
weil, weil die Zuweisung=
eine höhere Priorität hat als der Kommaoperator,
. Der Kommaoperator hat die niedrigste Priorität von allen.expression1, expression2;
zuerstexpression1
ausgewertet, vermutlich auf seine Nebenwirkungen (wie das Aufrufen einer Funktion), dann gibt es einen Sequenzpunkt, dannexpression2
wird ausgewertet und der Wert zurückgegeben…Ich habe am häufigsten in
while
Schleifen verwendet gesehen:Es wird die Operation ausführen und dann einen Test basierend auf einer Nebenwirkung durchführen. Der andere Weg wäre, es so zu machen:
quelle
while (read_string(s) && s.len() > 5)
. Offensichtlich würde das nicht funktionieren, wennread_string
es keinen Rückgabewert gibt (oder keinen aussagekräftigen). (Edit: Sorry, habe nicht bemerkt, wie alt dieser Beitrag war.)while (1)
mit einerbreak;
Aussage im Körper zu verwenden. Der Versuch, den ausbrechenden Teil des Codes in den while-Test oder in den do-while-Test zu zwingen, ist oft eine Energieverschwendung und erschwert das Verständnis des Codes.while(1)
undbreak
;Der Kommaoperator wertet den linken Operanden aus, verwirft das Ergebnis und wertet dann den rechten Operanden aus, und das ist das Ergebnis. Die im Link angegebene idiomatische Verwendung erfolgt beim Initialisieren der in einer
for
Schleife verwendeten Variablen und gibt das folgende Beispiel:Ansonsten gibt es nicht viele großartige Verwendungsmöglichkeiten für den Kommaoperator , obwohl es leicht zu missbrauchen ist, Code zu generieren, der schwer zu lesen und zu warten ist.
Nach dem Entwurf des C99-Standards lautet die Grammatik wie folgt:
und Absatz 2 sagt:
In Fußnote 97 heißt es:
Dies bedeutet, dass Sie dem Ergebnis des Kommaoperators keine Zuordnung zuweisen können .
Es ist wichtig zu beachten, dass der Kommaoperator die niedrigste Priorität hat. Daher gibt es Fälle, in denen die Verwendung
()
einen großen Unterschied machen kann, zum Beispiel:wird die folgende Ausgabe haben:
quelle
Der Kommaoperator kombiniert die beiden Ausdrücke auf beiden Seiten zu einem und wertet beide in der Reihenfolge von links nach rechts aus. Der Wert der rechten Seite wird als Wert des gesamten Ausdrucks zurückgegeben.
(expr1, expr2)
ist wie,{ expr1; expr2; }
aber Sie können das Ergebnis vonexpr2
in einem Funktionsaufruf oder einer Zuweisung verwenden.In
for
Schleifen wird häufig festgestellt, dass mehrere Variablen wie folgt initialisiert oder verwaltet werden:Abgesehen davon habe ich es nur "in Wut" in einem anderen Fall verwendet, wenn zwei Operationen zusammengefasst wurden, die immer in einem Makro zusammenpassen sollten. Wir hatten Code, der verschiedene Binärwerte in einen Bytepuffer zum Senden in ein Netzwerk kopierte, und einen Zeiger, der dort beibehalten wurde, wo wir waren:
Wo die Werte
short
s oderint
s waren, haben wir dies getan:Später lesen wir, dass dies kein wirklich gültiges C war, da
(short *)ptr
es kein l-Wert mehr ist und nicht inkrementiert werden kann, obwohl es unserem damaligen Compiler nichts ausmachte. Um dies zu beheben, teilen wir den Ausdruck in zwei Teile:Dieser Ansatz beruhte jedoch darauf, dass alle Entwickler daran dachten, beide Anweisungen ständig einzugeben. Wir wollten eine Funktion, mit der Sie den Ausgabezeiger, den Wert und den Werttyp übergeben können. Da dies C und nicht C ++ mit Vorlagen ist, konnte keine Funktion einen beliebigen Typ annehmen, daher haben wir uns für ein Makro entschieden:
Mit dem Komma-Operator konnten wir dies in Ausdrücken oder als Anweisungen verwenden, wie wir wollten:
Ich schlage nicht vor, dass eines dieser Beispiele einen guten Stil hat! In der Tat erinnere ich mich an Steve McConnells Code Complete, der davon abgeraten hat, Kommaoperatoren in einer
for
Schleife zu verwenden: Aus Gründen der Lesbarkeit und Wartbarkeit sollte die Schleife nur von einer Variablen gesteuert werden, und die Ausdrücke in derfor
Zeile selbst sollten nur Code für die Schleifensteuerung enthalten. keine anderen zusätzlichen Teile der Initialisierung oder Schleifenwartung.quelle
Es bewirkt die Auswertung mehrerer Anweisungen, verwendet jedoch nur die letzte als resultierenden Wert (rvalue, glaube ich).
So...
sollte dazu führen, dass x auf 8 gesetzt wird.
quelle
Wie in früheren Antworten angegeben, werden alle Anweisungen ausgewertet, die letzte wird jedoch als Wert des Ausdrucks verwendet. Persönlich fand ich es nur in Schleifenausdrücken nützlich:
quelle
Der einzige Ort, an dem ich gesehen habe, dass es nützlich ist, ist, wenn Sie eine funky Schleife schreiben, in der Sie mehrere Dinge in einem der Ausdrücke ausführen möchten (wahrscheinlich den Init-Ausdruck oder den Schleifenausdruck. So etwas wie:
Verzeihen Sie mir, wenn es Syntaxfehler gibt oder wenn ich etwas eingemischt habe, das nicht streng C ist. Ich behaupte nicht, dass der Operator in guter Form ist, aber dafür könnten Sie ihn verwenden. Im obigen Fall würde ich wahrscheinlich
while
stattdessen eine Schleife verwenden, damit die mehrfachen Ausdrücke auf init und loop offensichtlicher sind. (Und ich würde i1 und i2 inline initialisieren, anstatt zu deklarieren und dann zu initialisieren ... bla bla bla.)quelle
Ich belebe dies einfach, um Fragen von @Rajesh und @JeffMercado zu beantworten, die ich für sehr wichtig halte, da dies einer der Top-Suchmaschinen-Hits ist.
Nehmen Sie zum Beispiel den folgenden Codeausschnitt
Es wird gedruckt
Der
i
Fall wird wie in den meisten Antworten erläutert behandelt. Alle Ausdrücke werden in der Reihenfolge von links nach rechts ausgewertet, aber nur der letzte wird zugewieseni
. Das Ergebnis des(
Ausdrucks )is
1`.Der
j
Fall folgt unterschiedlichen Prioritätsregeln, da er,
die niedrigste Operatorpriorität hat. Aufgrund dieser Regeln sieht der Compiler Zuweisungsausdruck, konstant, konstant ... . Die Ausdrücke werden wieder in von links nach rechts ausgewertet und ihre Nebenwirkungen bleiben sichtbar, daherj
ist5
als Ergebnisj = 5
.Interessanterweise
int j = 5,4,3,2,1;
ist die Sprachspezifikation nicht zulässig. Ein Initialisierer erwartet einen Zuweisungsausdruck, sodass ein direkter,
Operator nicht zulässig ist.Hoffe das hilft.
quelle