Hierarchie bei Abarbeitung von Inkrementoperation
-
Hallo Skym0sh0,
vielen Dank für die Antwort !!
-
ich meine aber, dass ich mal irgendwo gelesen hab, dass sowas von rechts nach links ausgewertet wird...
-
Danke auch an dot !
-
Jochen911 schrieb:
Warum ist das Ergebnis undefiniert ? Es wird doch eine int Variable x mit 2 initialisiert und eine Operation mit (++x) (hier ist also ++x eindeutig der Wert 3 zugeweisen, oder ?)
nein, weil nicht definiert ist, welche der Operation zuerst vollständig(!) ausgeführt wird. Im C++-Standard ist diese Operation ausdrücklich als undefiniert spezifiziert:
Kapitel 5 Expressions; Absatz 4
Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression.
[Example:
i = v[i++]; // the behavior is unspecified
i = 7, i++, i++; // i becomes 9
i = ++i + 1; // the behavior is unspecified
i = i + 1; // the value of i is incremented
—end example]man beachte insbesondere die Zeile 'i = ++i + 1;' - natürlich muss der Wert (aber nicht der Speicher!) von i zuerst um 1 erhöht werden, bevor zusätzlich 1 addiert wird, aber es ist nicht definiert, wann der inkrementierte Wert an den Speicher von i zugewiesen wird. Vor oder nach der Zuweisung an das i durch den operator=. Also das Ergebnis darf sowohl i+1 als auch i+2 sein - beides wäre denkbar.
-
Werner_logoff schrieb:
Kapitel 5 Expressions; Absatz 4
Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression.
[Example:
i = v[i++]; // the behavior is unspecified
i = 7, i++, i++; // i becomes 9
i = ++i + 1; // the behavior is unspecified
i = i + 1; // the value of i is incremented
—end example]man beachte insbesondere die Zeile 'i = ++i + 1;' - natürlich muss der Wert (aber nicht der Speicher!) von i zuerst um 1 erhöht werden, bevor zusätzlich 1 addiert wird, aber es ist nicht definiert, wann der inkrementierte Wert an den Speicher von i zugewiesen wird. Vor oder nach der Zuweisung an das i durch den operator=. Also das Ergebnis darf sowohl i+1 als auch i+2 sein - beides wäre denkbar.
Nach dem ersten Satz müsste das Verhalten undefiniert sein, da i zweimal modifiziert wird. Wieso ist es nur unspezifiziert?
-
@Jochen911
Ich hoffe, dass die Frage aus reinem Interesse ist und dass du nicht vor hast, jemals etwas derartiges in deinem Code zu verwenden.
-
Unspezifiziert heißt, das Verhalten wird durch die Implementierung definiert, muss aber nicht dokumentiert werden. Undefiniert heißt, über das Verhalten kann keine Angabe gemacht werden, also auch die Compilerhersteller wissen nicht, was passiert.
Im vorliegenden Fall ist die Auswertereihenfolge aber grundsätzlich durch die Implementierung festgelegt. Darauf kann man sich zwar nicht verlassen, es steht nicht in der Doku, es kann bei verschiedenen Compilern, Compilerversionen und sogar verschiedenen Ausdrücken unterschiedlich sein, aber theoretisch könnte es mir der Compilerhersteller für einen bestimmten Ausdruck in einem bestimmten Kontext sagen. Es ist also "nur" unspezifiziert.
-
ipsec: Soll das eine Antwort auf meine Frage sein?
-
Ja. Wo liest du im ersten Satz, dass es undefiniert sein sollte? Das wird zwar im Forum oft so gesagt, ist aber ungenau.
Edit: ach so, du beziehst dich wohl auf Werners Antwort. Ich dachte du meinst den Standard.
-
Bashar schrieb:
Werner_logoff schrieb:
Kapitel 5 Expressions; Absatz 4
Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression.
[Example:
i = v[i++]; // the behavior is unspecified
i = 7, i++, i++; // i becomes 9
i = ++i + 1; // the behavior is unspecified
i = i + 1; // the value of i is incremented
—end example]man beachte insbesondere die Zeile 'i = ++i + 1;' - natürlich muss der Wert (aber nicht der Speicher!) von i zuerst um 1 erhöht werden, bevor zusätzlich 1 addiert wird, aber es ist nicht definiert, wann der inkrementierte Wert an den Speicher von i zugewiesen wird. Vor oder nach der Zuweisung an das i durch den operator=. Also das Ergebnis darf sowohl i+1 als auch i+2 sein - beides wäre denkbar.
Nach dem ersten Satz müsste das Verhalten undefiniert sein, da i zweimal modifiziert wird. Wieso ist es nur unspezifiziert?
Weil das Beispiel fehlerhaft kommentiert ist, das trifft ja noch auf ein paar andere Beispiele im Standard zu, also mit Vorsicht genießen. Beispiele sind sowieso nicht normativ.
-
Hm. Und da habe ich erst heute zufällig die Definitionen gelesen (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3290.pdf):
undefined behavior
behavior for which this International Standard imposes no requirementsunspecified behavior
behavior, for a well-formed program construct and correct data, that depends on the implementationNaja whatever. Im Prinzip ist es ja auch egal, in beiden Fällen sollte man es in keinem Programm haben.
-
camper schrieb:
Weil das Beispiel fehlerhaft kommentiert ist, das trifft ja noch auf ein paar andere Beispiele im Standard zu, also mit Vorsicht genießen.
Danke für die Bestätigung.
-
icarus2 schrieb:
@Jochen911
Ich hoffe, dass die Frage aus reinem Interesse ist und dass du nicht vor hast, jemals etwas derartiges in deinem Code zu verwenden.
Hallo icarus2,
ja, du hast recht, die Frage war nur interessehalber (bin zufällig darauf gestossen, als ich mich mit Makros beschäftigt habe):
z.B. ist so etwas gefährlich :
#define QUAD(x) (x*x)Nutzt man nämlich irgendwo im Source Code
QUAD(++x)kommt genau die besprochene Undefiniertheit ins Spiel.
Nutzt man dagegen eine inline Funktionsdefinition wie folgt
inline int quad( int x) { return (x*x); }tritt beim Aufruf
int x = 2; cout << quad (++x);keine Undefiniertheit auf.
Selbstverständlich würde ich so etwas nicht programmieren, war reines Interesse.
Danke nochmal an alle, die sich an der Diskussion beteiligt haben.