Nachdem ich diese Antwort über undefiniertes Verhalten und Sequenzpunkte gelesen hatte , schrieb ich ein kleines Programm:
#include <stdio.h>
int main(void) {
int i = 5;
i = (i, ++i, 1) + 1;
printf("%d\n", i);
return 0;
}
Die Ausgabe ist 2
. Oh Gott, ich habe das Dekrement nicht kommen sehen! Was passiert hier?
Außerdem habe ich beim Kompilieren des obigen Codes eine Warnung erhalten, die besagt:
px.c: 5: 8: Warnung: Der linke Operand des Kommaausdrucks hat keine Auswirkung
[-Wunused-value] i = (i, ++i, 1) + 1; ^
Warum? Aber wahrscheinlich wird es automatisch durch die Antwort auf meine erste Frage beantwortet.
printf("2\n");
Antworten:
Im Ausdruck
(i, ++i, 1)
ist das verwendete Komma der KommaoperatorDa es seinen ersten Operanden verwirft, ist es im Allgemeinen nur dann nützlich, wenn der erste Operand wünschenswerte Nebenwirkungen hat . Wenn der Nebeneffekt zum ersten Operanden nicht auftritt, generiert der Compiler möglicherweise eine Warnung über den Ausdruck ohne Auswirkung.
Im obigen Ausdruck wird also das am weitesten links stehende
i
ausgewertet und sein Wert verworfen. Dann++i
wird ausgewertet undi
um 1 erhöht, und der Wert des Ausdrucks++i
wird erneut verworfen, aber die Nebenwirkung voni
ist dauerhaft . Dann1
wird ausgewertet und der Wert des Ausdrucks wird1
.Es ist äquivalent zu
Beachten Sie, dass der obige Ausdruck vollkommen gültig ist und kein undefiniertes Verhalten hervorruft, da zwischen der Auswertung des linken und rechten Operanden des Kommaoperators ein Sequenzpunkt liegt .
quelle
i
wird mit initialisiert5
. Schauen Sie sich die Erklärung anint i = 5;
.++i
wird dieser Ausdruck ausgewertet,i
inkrementiert und dieser inkrementierte Wert ist der Wert des Ausdrucks. In diesem Falli++
wird dieser Ausdruck ausgewertet, der alte Wert voni
ist der Wert des Ausdrucks undi
wird jederzeit zwischen dem vorherigen und dem nächsten Sequenzpunkt des Ausdrucks erhöht.Zitat aus
C11
Kapitel6.5.17
, Komma-OperatorAlso, in deinem Fall,
wird bewertet als
i
, wird als ungültiger Ausdruck ausgewertet, Wert verworfen++i
, wird als ungültiger Ausdruck ausgewertet, Wert verworfen1
wurde der Wert zurückgegeben.Die endgültige Aussage sieht also so aus
und
i
kommt zu2
. Ich denke, dies beantwortet Ihre beiden Fragen.i
bekommt man einen Wert 2?Hinweis: FWIW, da nach der Auswertung des linken Operanden ein Sequenzpunkt vorhanden ist, ruft ein Ausdruck wie
(i, ++i, 1)
UB nicht auf, wie man im Allgemeinen versehentlich denken kann .quelle
i
eindeutig keine Wirkung hat! Ich glaube jedoch nicht, dass es für einen Mann so offensichtlich war, der den Kommaoperator nicht kennt (und ich wusste nicht, wie ich nach Hilfe suchen sollte, außer eine Frage zu stellen). Schade, dass ich so viele Downvotes bekommen habe! Ich werde die anderen Antworten überprüfen und dann entscheiden, welche zu akzeptieren sind. Vielen Dank! Schöne Top Antwort übrigens.Lassen Sie es uns Schritt für Schritt analysieren.
So erhalten wir 2. Und die endgültige Aufgabe jetzt:
Was auch immer in war ich , bevor es jetzt überschrieben.
quelle
++i
nicht zum Ergebnis beiträgt.int i = 0; for( ;(++i, i<max); )
Das Ergebnis von
ist
Zum
Die Auswertung erfolgt so, dass der
,
Bediener den ausgewerteten Wert verwirft und genau den am weitesten rechts liegenden Wert beibehält1
So
quelle
Auf der Wiki-Seite finden Sie einige gute Informationen für den Komma-Operator .
Grundsätzlich ist es
Dies bedeutet, dass
wird seinerseits bewerten
i
, das Ergebnis verwerfen, bewerteni++
, das Ergebnis verwerfen und dann bewerten und zurückgeben1
.quelle
(void)exp; a= exp2;
während ich nur brauchtea = exp, exp2;
)Sie müssen wissen, was der Kommaoperator hier tut:
Dein Ausdruck:
Der erste Ausdruck
i
wird ausgewertet, der zweite Ausdruck++i
wird ausgewertet und der dritte Ausdruck1
wird für den gesamten Ausdruck zurückgegeben.Das Ergebnis ist also :
i = 1 + 1
.Wie Sie sehen, hat der erste Ausdruck für Ihre Bonusfrage
i
überhaupt keine Wirkung, daher beschwert sich der Compiler.quelle
Komma hat eine "umgekehrte" Priorität. Dies erhalten Sie aus alten Büchern und C-Handbüchern von IBM (70er / 80er Jahre). Der letzte 'Befehl' wird also im übergeordneten Ausdruck verwendet.
Im modernen C ist seine Verwendung seltsam, aber im alten C (ANSI) sehr interessant:
Während alle Operationen (Funktionen) von links nach rechts aufgerufen werden, wird nur der letzte Ausdruck als Ergebnis der bedingten 'while' verwendet. Dies verhindert die Behandlung von 'goto', um einen eindeutigen Befehlsblock beizubehalten, der vor der Zustandsprüfung ausgeführt werden soll.
BEARBEITEN: Dadurch wird auch ein Aufruf einer Handling-Funktion vermieden, die sich um die gesamte Logik der linken Operanden kümmern und so das logische Ergebnis zurückgeben kann. Denken Sie daran, dass wir in der Vergangenheit von C keine Inline-Funktion hatten. Dies könnte also einen Anrufaufwand vermeiden.
quelle