Sequenzpunkte in c

Lesezeit: 5 Minuten

Jagans Benutzeravatar
Jagan

Ein Sequenzpunkt in der imperativen Programmierung definiert jeden Punkt in der Ausführung eines Computerprogramms, an dem garantiert ist, dass alle Nebenwirkungen früherer Bewertungen durchgeführt wurden und noch keine Nebenwirkungen nachfolgender Bewertungen durchgeführt wurden.

Was bedeutet das? Kann das bitte jemand in einfachen Worten erklären?

  • mögliches Duplikat von Sequenzpunkten und Teilreihenfolge

    – jev

    16. Oktober 2013 um 13:06 Uhr

Benutzeravatar von paxdiablo
paxdiablo

Wenn ein Sequenzpunkt auftritt, bedeutet dies im Grunde, dass Ihnen garantiert ist, dass alle vorherigen Operationen abgeschlossen sind.

Das zweimalige Ändern einer Variablen ohne dazwischenliegenden Sequenzpunkt ist ein Beispiel für undefiniertes Verhalten.

Zum Beispiel, i = i++; ist undefiniert, weil es zwischen den beiden Änderungen an keinen Sequenzpunkt gibt i.

Beachten Sie, dass es nicht nur ist Ändern eine Variable zweimal, die ein Problem verursachen kann. Es ist eigentlich eine Änderung, die mit jeder anderen Verwendung verbunden ist. Die Norm verwendet den Begriff „Wertberechnung“. und Nebeneffekt” bei der Diskussion, wie die Dinge sequenziert werden. Zum Beispiel im Ausdruck a = i + i++das i (Wertberechnung) und i++ (Nebenwirkung) kann in beliebiger Reihenfolge durchgeführt werden.

Wikipedia hat eine Liste der Sequenzpunkte in den C- und C++-Standards, obwohl die endgültige Liste immer dem ISO-Standard entnommen werden sollte. Aus C11 Anhang C (paraphrasiert):


Im Folgenden sind die im Standard beschriebenen Sequenzpunkte aufgeführt:

  • Zwischen den Auswertungen des Funktionsbezeichners und tatsächlichen Argumenten in einem Funktionsaufruf und dem tatsächlichen Aufruf;
  • Zwischen den Auswertungen des ersten und zweiten Operanden der Operatoren &&, ||und ,;
  • Zwischen den Auswertungen des ersten Operanden der Bedingung ?: Operator und je nachdem, welcher der zweiten und dritten Operanden ausgewertet wird;
  • Das Ende eines vollständigen Deklarators;
  • Zwischen der Auswertung eines vollständigen Ausdrucks und dem nächsten auszuwertenden vollständigen Ausdruck. Das Folgende sind vollständige Ausdrücke:
    • ein Initialisierer;
    • der Ausdruck in einer Ausdrucksanweisung;
    • der steuernde Ausdruck einer Auswahlanweisung (if oder switch);
    • der kontrollierende Ausdruck von a while oder Aussage machen;
    • jeder der Ausdrücke von a for Aussage;
    • der Ausdruck in einer return-Anweisung.
  • Unmittelbar bevor eine Bibliotheksfunktion zurückkehrt;
  • Nach den Aktionen, die jedem formatierten Eingabe/Ausgabe-Funktionsumwandlungsspezifizierer zugeordnet sind;
  • Unmittelbar vor und unmittelbar nach jedem Aufruf einer Vergleichsfunktion und auch zwischen jedem Aufruf einer Vergleichsfunktion und jeder Bewegung der als Argumente an diesen Aufruf übergebenen Objekte.

  • Ich erwarte weitere Informationen von Ihnen Pax. Ich habe Grundkenntnisse in c. Sie haben meine vorherige Frage sehr gut erklärt.

    – Jagan

    26. August 2010 um 13:19 Uhr

  • Es ist auch ein undefiniertes Verhalten, den Wert einer Variablen zu ändern und den Wert auch auf andere Weise zu verwenden, als den zu speichernden Wert ohne einen dazwischenliegenden Sequenzpunkt zu bestimmen. Zum Beispiel ein[i++] = i ist undefiniert, weil, obwohl es den Wert von i nur einmal modifiziert, der Wert von i für einen anderen Zweck verwendet wird, als zu bestimmen, welcher Wert in i gespeichert werden soll.

    – Robert Gamble

    26. August 2010 um 13:23 Uhr

  • Irgendeine Idee, wie sich das mit OOE kombinieren lässt, oder ist das eine andere Abstraktionsebene?

    – Matt Tischler

    26. August 2010 um 14:25 Uhr

  • @Matt: Das ist eine Ebene der Abstraktion nach unten. Solange Sie korrekten C-Code schreiben, ist das Ergebnis dasselbe, unabhängig davon, ob Ihre Plattform OOE unterstützt oder nicht. Selbst wenn Sie falschen Code schreiben, sollten Sie dasselbe Ergebnis erhalten, da die ausführbare Binärdatei in jedem Fall dieselbe ist.

    – Oliver Charlesworth

    26. August 2010 um 15:22 Uhr

  • @Matt Joiner Wir müssen die Einschränkung hinzufügen: aus der Perspektive des Kontexts, in dem der Thread ausgeführt wird zu der ausgezeichneten Antwort oben. OOE ist im Allgemeinen für den Befehlsstrom unsichtbar – der Befehlsplaner der CPU muss sicherstellen, dass Datenabhängigkeiten zwischen Befehlen erfüllt werden. Wenn es um Speicher und Caches geht, ist es eine ganz andere Geschichte, und sowohl der C- als auch der C++-Standard sind sehr spezifisch in Bezug auf die Notwendigkeit, Speicherbarrieren zu verwenden, wenn die Reihenfolge der Fertigstellung aus Sicht des Speichers wichtig ist.

    – Marko

    16. Oktober 2013 um 13:23 Uhr

Bei Sequenzpunkten ist zu beachten, dass sie nicht global sind, sondern als eine Reihe lokaler Einschränkungen betrachtet werden sollten. Zum Beispiel in der Erklärung

a = f1(x++) + f2(y++);

Es gibt einen Sequenzpunkt zwischen der Auswertung von x++ und dem Aufruf von f1 und einen weiteren Sequenzpunkt zwischen der Auswertung von y++ und dem Aufruf von f2. Es gibt jedoch keine Garantie dafür, ob x vor oder nach dem Aufruf von f2 inkrementiert wird oder ob y vor oder nach dem Aufruf von x inkrementiert wird. Wenn f1 y oder f2 x ändert, sind die Ergebnisse undefiniert (es wäre legitim, wenn der vom Compiler generierte Code z es hat sich geändert — randalieren Sie und suchen und zerstören Sie alle Barney-Videos und -Waren; ich glaube leider nicht, dass echte Compiler Code generieren, der das tatsächlich tun würde, aber es wäre unter dem Standard erlaubt).

  • Wenn eine Funktion x oder y geändert hat, geschieht dies nach dem Sequenzpunkt (der unmittelbar vor dem eigentlichen Aufruf der Funktion). Das Verhalten ist nicht spezifiziert.

    – 2501

    3. Juni 2016 um 13:48 Uhr

Erweitern Sie die Antwort von Paxdiablo mit einem Beispiel.

Übernehmen Sie die Aussage

x = i++ * ++j;

Es gibt drei Seiteneffekte: Zuweisen des Ergebnisses von i * (j+1) zu x, 1 zu i addieren und 1 zu j addieren. Die Reihenfolge, in der die Nebenwirkungen angewendet werden, ist nicht angegeben; i und j können jeweils unmittelbar nach der Auswertung inkrementiert werden, oder sie können nicht inkrementiert werden, bis beide ausgewertet wurden, aber bevor x zugewiesen wurde, oder sie können nicht inkrementiert werden, bis x zugewiesen wurde.

Der Sequenzpunkt ist der Punkt, an dem alle Nebenwirkungen angewendet wurden (x, i und j wurden alle aktualisiert), unabhängig von der Reihenfolge, in der sie angewendet wurden.

  • Wir sollten jedoch darauf hinweisen, dass das Ergebnis von x = i++ * ++j ist im Gegensatz zu Paxdiablo gut definiert i = i++ Beispiel…

    – Oliver Charlesworth

    26. August 2010 um 15:17 Uhr

Das bedeutet, dass ein Compiler abgefahrene Optimierungen, Tricks und Magie ausführen kann, aber an diesen sogenannten Sequenzpunkten einen wohldefinierten Zustand erreichen muss.

1389930cookie-checkSequenzpunkte in c

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy