2010-09-11 7 views
15

Warum kompiliert das folgende in C++?Mehrere Vorinkrementierungen für eine Variable in C++ (C?)

int phew = 53; 
++++++++++phew ; 

Derselbe Code schlägt in C fehl, warum?

+0

C++ 0x-Tag nur zum Spaß hinzufügen. :) –

+1

Es muss eine Standardfrage geben, auf die wir uns für diese Art von Frage beziehen können. So können alle Fragen (die wir zu dieser Jahreszeit von neuen Studenten bekommen) einfach schnell geschlossen und markiert gelesen werden. –

Antwort

13

Das liegt daran, dass in C++ vorge Inkrementoperator gibt einen lvalue und seine Operanden erfordert ein lvalue zu sein.

++++++++++phew ; in interpretiert als ++(++(++(++(++phew))))

jedoch Ihren Code Undefined Behaviour ruft, weil Sie versuchen, den Wert von phew mehr zu ändern als einmal zwischen zwei sequence points.

In C, pre-increment Operator ein rvalue zurückgibt und erfordert seinen Operanden ein lvalue zu sein. Dein Code wird also nicht im C-Modus kompiliert.

+2

@Prasoon: Um nicht zu vermuten, bin ich nur neugierig, darüber zu lesen, was du gesagt hast; "Sie versuchen, den Wert von Puh mehr als einmal zwischen zwei Sequenzpunkten zu ändern". Können Sie diesem Teil des Standards eine Anmerkung hinzufügen, damit ich mehr darüber erfahren kann? –

+3

@Merlyn Morgan-Graham: Lesen Sie diesen Artikel von Steve Summit: http://c-faq.com/expr/seqpoints.html. –

+0

'Kommentar' Diese Spezifikation muss nur genau dann beachtet werden, wenn mehr als ein Zugriff zwischen der Sequenz Punkten oder für Objekte, die mit der flüchtigen Speicherklasse deklariert sind, besteht. Soweit der Entwickler betroffen ist, tritt eine Modifikation auf. Solange die Implementierung das erwartete Ergebnis liefert, ist es frei, alles zu tun, was auch immer es mag. –

27

Hinweis: Die beiden Fehlerberichte DR#637 und DR#222 sind wichtig, um das Grundprinzip des Verhaltens zu verstehen.


Zur Erläuterung in C++ 0x gibt es value computations und side effects. Ein Nebeneffekt ist beispielsweise eine Zuweisung, und eine Wertberechnung bestimmt, worauf sich ein L-Wert bezieht oder den Wert aus einem L-Wert liest. Beachten Sie, dass C++ 0x keine Sequenzpunkte mehr hat und dieses Zeug in Form von "vor Sequenz sequenziert" und "nach Sequenz sequenziert" formuliert ist. Und es heißt, dass

Wenn eine Nebenwirkung auf eine skalare Objekt ist unsequenced in Bezug auf entweder einen anderen Nebeneffekt auf demselben Skalar-Objekt oder ein Wertberechnung den Wert des gleichen Skalar-Objekt, das Verhalten nicht definiert ist.

++v entspricht v += 1 die zu v = v + 1 entspricht (außer daß v nur einmal bewertet wird). Dies ergibt , was ich als inc = inc + 1 schreiben werde, wobei sich inc auf das lvalue-Ergebnis von bezieht.

In C++ 0x ++ ++v ist nicht undefiniert Verhalten, weil für a = b die Zuweisung nach Wert Berechnung von b und a, aber vor Wert Berechnung des Zuweisungsausdrucks sequenziert wird. Daraus folgt, dass die Zuordnung in vor der Wertberechnung von inc sequenziert wird. Und die Zuordnung in inc = inc + 1 wird nach der Wertberechnung von inc sequenziert. Am Ende werden somit beide Zuordnungen sequenziert, und es gibt kein undefiniertes Verhalten.

+3

Gute Antwort. Ähnlich 'int a = 4; ++ a = 5; 'würde UB in C++ 0x nicht aufrufen, oder? –

+0

@ Prasoon ja. Es würde 'a' auf 5 setzen. Ebenso wird' a = ++ a; 'nicht UB sein, aber' a = a ++; 'wird UB sein. –

+0

@Johannes: Cool :-). Die Welt ändert sich. –