C Language
Folgepunkte
Suche…
Bemerkungen
Internationale Norm ISO / IEC 9899: 201x Programmiersprachen - C
Auf ein flüchtiges Objekt zuzugreifen, ein Objekt zu ändern, eine Datei zu ändern oder eine Funktion aufzurufen, die eine dieser Operationen ausführt , sind alles Nebeneffekte , die den Status der Ausführungsumgebung beeinflussen.
Das Vorhandensein eines Sequenzpunktes zwischen der Auswertung der Ausdrücke A und B impliziert, dass jede mit A verbundene Wertberechnung und Nebenwirkung vor jeder mit B verbundenen Wertberechnung und Nebenwirkung sequenziert wird.
Hier ist die vollständige Liste der Sequenzpunkte aus Anhang C des Online-Vorentwurfs der Veröffentlichung von 2011 für die C-Standardsprache:
Folgepunkte
1 Im Folgenden werden die in 5.1.2.3 beschriebenen Sequenzpunkte beschrieben:
- Zwischen den Auswertungen des Funktionsbezeichners und den tatsächlichen Argumenten in einem Funktionsaufruf und dem tatsächlichen Aufruf. (6.5.2.2).
- Zwischen den Bewertungen des ersten und des zweiten Operanden der folgenden Operatoren: logisches AND
&&
(6.5.13); logisches ODER||
(6.5.14); comma,
(6.5.17).- Zwischen den Bewertungen des ersten Operanden des Bedingten
? :
Operator und welcher der zweite und dritte Operand ausgewertet wird (6.5.15).- Das Ende eines vollständigen Deklarators: Deklaratoren (6.7.6);
- Zwischen der Auswertung eines vollständigen Ausdrucks und dem nächsten zu bewertenden vollen Ausdruck. Die folgenden Ausdrücke sind vollständige Ausdrücke: ein Initialisierer, der nicht Teil eines zusammengesetzten Literal (6.7.9) ist; der Ausdruck in einer Ausdrucksanweisung (6.8.3); der steuernde Ausdruck einer Auswahlanweisung (
if
oderswitch
) (6.8.4); die Steuerung der Expression eineswhile
oderdo
Anweisung (6.8.5); jeder der (optionalen) Ausdrücke einerfor
Anweisung (6.8.5.3); der (optionale) Ausdruck in einerreturn
Anweisung (6.8.6.4).- Unmittelbar bevor eine Bibliotheksfunktion zurückkehrt (7.1.4).
- Nach den Aktionen, die jedem formatierten Eingabe- / Ausgabefunktionsumwandlungsbezeichner zugeordnet sind (7.21.6, 7.29.2).
- Unmittelbar vor und unmittelbar nach jedem Aufruf einer Vergleichsfunktion sowie zwischen jedem Aufruf einer Vergleichsfunktion und jeder Bewegung der Objekte, die als Argumente an diesen Aufruf übergeben werden (7.22.5).
Sequenzierte Ausdrücke
Die folgenden Ausdrücke werden sequenziert :
a && b
a || b
a , b
a ? b : c
for ( a ; b ; c ) { ... }
In allen Fällen wird der Ausdruck a
vollständig ausgewertet und alle Nebenwirkungen werden angewendet, bevor entweder b
oder c
ausgewertet werden. Im vierten Fall wird nur eine von b
oder c
ausgewertet. Im letzten Fall wird b
vollständig ausgewertet und alle Nebenwirkungen werden angewendet, bevor c
ausgewertet wird.
In allen Fällen wird die Bewertung von Ausdruck a
vor den Bewertungen von b
oder c
sequenziert (alternativ werden die Bewertungen von b
und c
nach der Bewertung von a
) sequenziert .
So mögen Ausdrücke
x++ && x++
x++ ? x++ : y++
(x = f()) && x != 0
for ( x = 0; x < 10; x++ ) { ... }
y = (x++, x++);
gut definiertes Verhalten haben.
Nicht aufeinanderfolgende Ausdrücke
Die folgenden Ausdrücke sind nicht aufeinanderfolgend :
a + b;
a - b;
a * b;
a / b;
a % b;
a & b;
a | b;
In den obigen Beispielen kann der Ausdruck a
vor oder nach dem Ausdruck b
bewertet werden, b
kann vor a
ausgewertet werden, oder sie können sogar gemischt werden, wenn sie mehreren Anweisungen entsprechen.
Eine ähnliche Regel gilt für Funktionsaufrufe:
f(a, b);
Hier nicht nur a
und b
sind unsequenced (dh die ,
Operator in einem Funktionsaufruf keinen Sequenzpunkt erzeugen) , sondern auch f
, der Ausdruck, der die Funktion bestimmt , die aufgerufen werden soll.
Nebenwirkungen können unmittelbar nach der Bewertung angewendet oder auf einen späteren Zeitpunkt verschoben werden.
Ausdrücke wie
x++ & x++;
f(x++, x++); /* the ',' in a function call is *not* the same as the comma operator */
x++ * x++;
a[i] = i++;
oder
x++ & x;
f(x++, x);
x++ * x;
a[i++] = i;
wird unbestimmtes Verhalten ergeben, weil
- Eine Änderung eines Objekts und jeglicher anderer Zugriff darauf muss sequenziert werden
- Die Reihenfolge der Bewertung und die Reihenfolge, in der die Nebenwirkungen 1 angewendet werden, ist nicht festgelegt.
1 Alle Änderungen im Status der Ausführungsumgebung.
Unbestimmte sequenzierte Ausdrücke
Funktionsaufrufe als f(a)
implizieren immer einen Sequenzpunkt zwischen der Auswertung der Argumente und dem Bezeichner (hier f
und a
) und dem tatsächlichen Aufruf. Wenn zwei solcher Aufrufe nicht sequenziell sind, werden die beiden Funktionsaufrufe unbestimmt sequenziert, dh einer wird vor dem anderen ausgeführt, und die Reihenfolge ist nicht spezifiziert.
unsigned counter = 0;
unsingned account(void) {
return counter++;
}
int main(void) {
printf("the order is %u %u\n", account(), account());
}
Diese implizite zweifache Änderung des counter
während der Auswertung der printf
Argumente ist gültig. Wir wissen nur nicht, welcher der Aufrufe zuerst kommt. Da die Bestellung nicht spezifiziert ist, kann sie variieren und ist nicht abhängig. Der Ausdruck könnte also lauten:
die Reihenfolge ist 0 1
oder
Die Reihenfolge ist 1 0
Die analoge Aussage zu dem obigen ohne Zwischenfunktionsaufruf
printf("the order is %u %u\n", counter++, counter++); // undefined behavior
hat ein undefiniertes Verhalten, da es keinen Sequenzpunkt zwischen den beiden Modifikationen des counter
.