Order of evaluation
Die Reihenfolge der Auswertung der Operanden jedes C-Operators, einschließlich der Reihenfolge der Auswertung von Funktionsargumenten in einem Funktionsaufrufausdruck und der Reihenfolge der Auswertung der Teilausdrücke innerhalb eines Ausdrucks, ist nicht spezifiziert (außer wie unten angegeben). Der Compiler kann sie in beliebiger Reihenfolge auswerten und kann eine andere Reihenfolge wählen, wenn derselbe Ausdruck erneut ausgewertet wird.
In C gibt es kein Konzept von Links-nach-rechts oder Rechts-nach-links Auswertung, was nicht mit der Links-nach-rechts und Rechts-nach-links Assoziativität von Operatoren verwechselt werden darf: Der Ausdruck f1 ( ) + f2 ( ) + f3 ( ) wird aufgrund der Links-nach-rechts-Assoziativität des operator + als ( f1 ( ) + f2 ( ) ) + f3 ( ) geparst, aber der Funktionsaufruf f3 ( ) kann zur Laufzeit zuerst, zuletzt oder zwischen f1 ( ) und f2 ( ) ausgewertet werden.
Inhaltsverzeichnis |
Definitionen
Auswertungen
Es gibt zwei Arten von Auswertungen, die vom Compiler für jeden Ausdruck oder Teilausdruck durchgeführt werden (beide sind optional):
- Wertberechnung : Berechnung des Werts, der durch den Ausdruck zurückgegeben wird. Dies kann die Bestimmung der Identität des Objekts ( Lvalue-Auswertung ) oder das Lesen eines zuvor einem Objekt zugewiesenen Werts (Rvalue-Auswertung) umfassen.
-
Nebeneffekt
: Zugriff (Lesen oder Schreiben) auf ein durch einen
volatileLvalue bezeichnetes Objekt, Modifikation (Schreiben) eines Objekts , atomare Synchronisation (seit C11) , Modifizieren einer Datei, Ändern der Gleitkommaumgebung (falls unterstützt) oder Aufruf einer Funktion, die eine dieser Operationen durchführt.
Wenn ein Ausdruck keine Nebeneffekte erzeugt und der Compiler feststellen kann, dass der Wert nicht verwendet wird, kann der Ausdruck möglicherweise nicht ausgewertet werden .
Reihenfolge
Sequenced-before ist eine asymmetrische, transitive, paarweise Beziehung zwischen Auswertungen innerhalb desselben Threads (sie kann sich über Threads hinweg erstrecken, wenn atomare Typen und Speicherbarrieren beteiligt sind).
- Wenn ein Sequence Point zwischen den Teilausdrücken E1 und E2 vorhanden ist, dann sind sowohl Wertberechnung als auch Seiteneffekte von E1 sequenced-before jeder Wertberechnung und jedem Seiteneffekt von E2 .
|
(seit C11) |
Regeln
&&
(logisches UND),
||
(logisches ODER), und
,
(Komma).
?:
|
5)
Es gibt einen Sequenzpunkt am Ende eines vollständigen Deklarators.
6)
Es gibt einen Sequenzpunkt unmittelbar vor der Rückgabe einer Bibliotheksfunktion.
7)
Es gibt einen Sequenzpunkt nach der Aktion, die mit jedem Konvertierungsspezifizierer in der formatierten E/A verbunden ist (insbesondere ist es wohlgeformt, wenn
scanf
verschiedene Felder in dieselbe Variable schreibt und wenn
printf
dieselbe Variable mehrfach liest und modifiziert oder modifiziert unter Verwendung von
%
n
)
|
(seit C99) |
|
9)
Die Wertberechnungen (aber nicht die Nebeneffekte) der Operanden jedes Operators sind vor der Wertberechnung des Ergebnisses des Operators (aber nicht dessen Nebeneffekten) sequenziert.
10)
Der Nebeneffekt (Modifikation des linken Arguments) des direkten Zuweisungsoperators und aller zusammengesetzten Zuweisungsoperatoren ist nach der Wertberechnung (aber nicht den Nebeneffekten) sowohl des linken als auch des rechten Arguments sequenziert.
11)
Die Wertberechnung der Post-Inkrement- und Post-Dekrement-Operatoren ist vor deren Nebeneffekt sequenziert.
12)
Ein Funktionsaufruf, der nicht vor oder nach einem anderen Funktionsaufruf sequenziert ist, ist unbestimmt sequenziert (CPU-Befehle, die verschiedene Funktionsaufrufe bilden, können nicht verschachtelt werden, selbst wenn die Funktionen inline sind)
13)
In
Initialisierungslistenausdrücken
sind alle Auswertungen unbestimmt sequenziert
14)
Bezüglich eines unbestimmt sequenzierten Funktionsaufrufs sind die Operationen der zusammengesetzten Zuweisungsoperatoren sowie sowohl die Präfix- als auch die Postfix-Formen der Inkrement- und Dekrement-Operatoren einzelne Auswertungen.
|
(seit C11) |
Undefiniertes Verhalten
i = ++i + i++; // undefined behavior i = i++ + 1; // undefined behavior f(++i, ++i); // undefined behavior f(i = -1, i = -1); // undefined behavior
f(i, i++); // undefined behavior a[i] = i++; // undefined behavior
Siehe auch
Operator-Präzedenz die definiert, wie Ausdrücke aus ihrer Quellcode-Darstellung aufgebaut werden.
|
C++ Dokumentation
für
Auswertungsreihenfolge
|