2010-12-06 6 views
19

Gibt es einen guten Grund dafür, dass operator = kein Sequenzpunkt ist? Sowohl in C als auch in C++.Gibt es einen guten Grund, warum der Zuweisungsoperator kein Sequenzpunkt ist?

Ich habe Probleme, über ein Gegenbeispiel nachzudenken.

+0

Dazu müsste der Compiler die LHS vor dem RHS berechnen. Warum sollten Sie diese Art von Einschränkung erstellen? –

+2

'a = b = c = 0;' – pmg

+7

Im Allgemeinen brauchen die Dinge einen Grund, ** ein Sequenzpunkt zu sein **. Sie brauchen keinen Grund ** nicht ** als Sequenzpunkt; Das ist die Standardeinstellung. –

Antwort

20

Auf Anfrage:

Im Allgemeinen Dinge brauchen einen Grund, zu eine Folge Punkt. Sie brauchen keinen Grund nicht, um ein Sequenzpunkt zu sein; Das ist die Standardeinstellung.

Zum Beispiel && muss ein Sequenzpunkt sein, weil das Kurzschlussverhaltens: Wenn die linke Seite falsch ist, die rechte Seite darf nicht ausgewertet werden. (Es geht nicht nur um Optimierung; die rechte Seite könnte Nebenwirkungen haben und/oder davon abhängen, dass die linke Seite wahr ist, wie in ptr && ptr->data.) Daher muss die linke Seite zuerst bewertet werden, vor der rechten Seite - Handseite, um zu sehen, ob die rechte Seite überhaupt ausgewertet werden sollte.

Dieser Grund existiert nicht für = da, obwohl es „Auswertung“ für beiden Seiten zu tun ist (obwohl es verschiedene Einschränkungen auf, was auf beiden Seiten erscheinen: die linke Seite einen L-Wert sein muss - die l steht nicht für "left", sondern steht für "location", wie in location in memory - wir können weder einem temporären noch einem literal zuweisen), egal welche Seite zuerst ausgewertet wird - so lange da beide Seiten vor der eigentlichen Aufgabe ausgewertet werden.

+3

+1, aber '=' nicht ein Sequenzpunkt habe mich einmal gebissen: Ich hatte 'myArray [i ++] = ;', und einer von zwei Compilern berechnet die RHS "nach" der LHS, die Produktion der falsche Antwort. Meine Schuld am Ende, aber trotzdem knifflig. –

+0

IIRC und FWIW, Java bietet hier mehr Garantien :) –

+0

Das Kurzschlussverhalten an sich würde keinen Sequenzpunkt erfordern. Ein Ausdruck wie '(((ch = * x ++)! = 0) && (* y ++ = ch))' könnte, * aber für die explizite Anforderung, dass && einen Sequenzpunkt * vorgibt, das Inkrement von x bis nach der Ausführung verzögern des zweiten Teils des Ausdrucks, da der Compiler vor dem Inkrementieren von x bestimmen könnte, ob der linke Operand von '&&' zu Null ausgewertet würde oder nicht. In der Praxis ist es unwahrscheinlich, dass irgendwelche der durch den Sequenzpunkt verbotenen Codeumlagerungen ansonsten nützlich wären, aber in einigen theoretischen Fällen könnten sie dies sein. – supercat

0

Es ist (eine Art). Der Operator = (der vom Bearbeiter definiert werden kann (aka der benutzerdefinierte Operator = für Klassentypen) ist nur syntaktischer Zucker für einen Funktionsaufruf. Als Ergebnis hat es die gleiche "Sequenzpunkt" -Semantik wie ein Funktionsaufruf.

Wenn wir über eingebaute Typen gehen, dann denke ich, dass es eine gute Sache ist.
Sie möchten nicht zu viele Sequenzpunkte einführen, da dies die Optimierung behindert.

+2

Es ist nur syntaktischer Zucker für einen Funktionsaufruf für benutzerdefinierte Klassen in C++. Während Sie das implizieren, ist es überhaupt nicht klar von der Art, wie Sie es formuliert haben. –

+6

'Sequenzpunkt "Semantik', die jedoch nicht besonders nützlich sind - weil die Argumente zu' operator = 'die LHS und RHS des' = 'Zeichens sind, und Funktionsaufrufe keine Reihenfolge bei der Auswertung von ihre Argumente - nur die Auswertung der Funktion selbst ist ein Sequenzpunkt. –

0

Es gibt viele Gründe, nicht zu verlangen, dass eine Seite vor der anderen ausgewertet wird. Eine interessantere Frage ist, ob die Bewertung der beiden Seiten, einschließlich der Nebenwirkungen, erforderlich sein sollte, bevor der Zuweisungsoperator selbst etwas unternimmt. Ich würde vorschlagen, dass eine solche Anforderung einige Aliasing-Beschränkungen erleichtern würde, in einigen Fällen jedoch mehr Arbeit für einen Compiler erfordert. Angenommen, "foo" und "bar" sind Zeiger auf große Strukturen, deren Adressen sich überlappen würden. Die Aussage "* foo = * bar;" würde ein undefiniertes Verhalten unter dem aktuellen Standard darstellen. Wenn es zwischen der Auswertung der Operanden und der Zuweisung einen Sequenzpunkt gäbe, würde eine solche Aussage garantiert "funktionieren". Eine solche Garantie würde für den Zuweisungsoperator komplizierter sein, was einen größeren und langsameren Code erfordert, selbst wenn sich die Zeiger in der Praxis niemals überschneiden.

Beispiel:

 
unsigned char foo[100]; 
typedef struct {int x, int y;} POINT; 
POINT *p1 = (POINT*)foo; 
POINT *p2 = (POINT*)(&(p1->y)); 

die obigen Erklärungen gegeben, ich glaube, die folgenden Aussagen haben die streng definierten Verhaltensweisen angegeben und beinhalten keine undefinierten Verhalten.

 
    p1->y = somevalue; // Sets p2->x to somevalue 
    p2->x = somevalue; // Sets p1->y to somevalue 
    *p1 = mystruct;  // Sets p2->x to mystruct.y 
    *p2 = mystruct;  // Sets p1->x to mystruct.x 

Die beiden folgenden Anweisungen würde jedoch nicht definiertes Verhalten beinhalten:

 
    *p1 = *p2; 
    *p2 = *p1; 

Wenn es eine Sequenz Punkt, an dem Gleichheitszeichen, so hätte ein Compiler entweder P1 und P2 vergleichen, oder Kopieren Sie den Quelloperanden an einen temporären Speicherort und kopieren Sie ihn anschließend an das Ziel. Der Standard macht jedoch deutlich, dass die beiden obigen Aussagen beide als Undefined Behavior gelten. Der Standard erfordert Compiler, um Code zu erzeugen, der beim Kopieren einer Struktur in eine nicht überlappende Struktur korrekt funktioniert, aber keine Einschränkung dafür, was Compiler tun können, wenn sich die Strukturen überschneiden. Ein Compiler, der den Prozessor in eine Schleife schickt, die "Frink Rules!" aus jedem offenen TCP-Socket würde dadurch nicht gegen den Standard verstoßen.

+0

"_große Strukturen, deren Adressen sich überlappen würden._" Können Sie ein Beispiel geben? – curiousguy

+0

Du hast diesen "Frink-Regeln" -Satz aus der Homer-3D-Episode von "Die Simpsons", nicht wahr? – ninjalj

+0

@curiousguy: Siehe Beispiel. – supercat

Verwandte Themen