C Frage zu Inkrementoperatoren ++i, i++

Lightee

Ensign
Registriert
Jan. 2010
Beiträge
234
Hallo Leute,

eine Frage bzgl. der Inkrementoperatoren. Grundsätzlich kann man ja sagen, dass:
#####################
i = 1;
j = ++i;
(i is 2, j is 2)
#####################
i = 1;
j = i++;
(i is 2, j is 1)
#####################

Nun zu einem konkreten Beispiel:

int z = 100;
z = z + ++z;
return z; // z == 202

Warum ist z am Ende 202? Ich verstehe die "theoretische Definition vom Unterschied zwischen ++i und i++, kann es aber in dem Bsp. gar nicht umsetzen/verstehen.

Danke
 
Der voranstehende Inkrementoperator wird intern ganz offensichtlich vor dem kompletten Ausdruck ausgeführt.

Aus deinem
z = z + ++z;

wird also
z = z + 1; //100+1=101
z = z + z; //101+101=202
 
Nur eine Vermutung: vielleicht liegt es an den Vorrangregeln? Es wird zuerst ++z ausgewertet (ergibt dann 101). Danach wird dann z + 101 gerechnet. z ist aber mittlerweile schon 101, daher 101 + 101 = 202. Weiß nichtg, ob das richtig ist, aber könnte ich mir vorstellen.

Gruß ete

zu langsam :)
 
Als Prefix "++z" wird der Operator vor dem restlichen Ausdruck ausgewertet, somit ist z = 101 + 101 = 202.
 
anderes Beispiel
int i = 1;
a)
int j = i++; // j wird 1, i wird 2

b)
int j = ++i; // i wird 2, j wird 2
 
Das selbe Beispiel hat er doch schon in seinem Startpost verfasst :p
Wie schon gesagt, der "++z"-Operator wird anscheinend als aller erstes ausgewertet.
Hier ist das auch nochmal gut erklärt.
 
Dass "++" einen so hohen Stellenwert hat, erklärt alles.

DANKE!
 
BROKENDREAM schrieb:
Dass "++" einen so hohen Stellenwert hat, erklärt alles.

DANKE!

Das ist aber nicht die richtige Erklärung. Es stimmt zwar, dass unäre Operatoren eine höhere Präzedenz besitzen, als binäre, aber es ist dem Compiler nicht vorgeschrieben, ob er zuerst den linken oder rechten Operanden einer Operation auswertet.
Es kann genausogut passieren, dass der linke Operand zuerst auf den Stack gepusht wird und anschließend der unäre Ausdruck ++z ausgewertet und auf den Stack geschrieben wird.
Dann wäre das Ergebnis 201. Die Präzedenz legt lediglich fest, dass ++z vor der +-Operation ausgewertet werden muss, aber nicht, dass dies vor dem 2. Operanden geschehen muss.

Das schließt jetzt natürlich nicht aus, dass der Compiler selbst darauf achtet, dass Operanden mit der Inkrementierungsanweisung zuerst ausgewertet werden. Das weißt du spätestens, wenn du die Operanden einmal vertauscht. Das gilt dann aber trotzdem nicht für jeden Compiler und jede Sprache.
 
werft mal einen blick ins dissassembly,

aus
Code:
int j = i++;
wird das selbe wie aus
Code:
int j = i;
i++;

auch der sinn hinter dem
Code:
++i;
wird sofort ersichtlich, und bedeutet nämlich
Code:
i++;
int j = i;
 
Ich sehe das genau wie kinglouy. Es stimmt nicht, dass ++z eine so hohe Präferenz hat, dass es vor der kompletten Anweisung ausgeführt wird. Und darauf sollte man sich auch nicht verlassen. Ich habe es eben mal mit gcc und clang getestet.. heraus kam 202 und 201.
Was hier korrekt ist kann man nur schwer sagen. Müsste man ggf. in der Sprachdefinition von C++ nachlesen ob es eine bestimmte Regelung für solche Dinge gibt.

Grundsätzlich kannst du nämlich zwei Ansätze betrachen:
1) Atomare Zustandsübergänge
d.h. es wird innerhalb einer Anweisung mit den Werten gearbeitet, die _vor_ der Anweisung aktuell sind. Innerhalb einer Anweisung können damit keine Zwischenzustände entstehen (ergibt 201).

2) Nicht atomare Zustandsübergange
d.h. es sind Zwischenzustände möglich und Variablen können sich innerhalb einer einzelnen Anweisung verändern (ergibt 201 ODER 202, je nach Reihenfolge der Auswertung).
 
Zuletzt bearbeitet:
@IceMatrix: Nicht vor der kompletten Anweisung, aber dann wenn das Token "++z" ausgewertet werden soll, wird z erhöht und das erhöhte z verwendet. Aber du hast schon recht, auf die Reihenfolge in der die einzelnen Teilausdrücke ausgewertet werden, sollte man sich nicht verlassen.
 
Hier was das Pfadfinderbuch des Fähnlein Fieselschweif, äh ich meine der C++-Standard dazu sagt. ;)

4 Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified.
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.
Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined. {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}
 
Gut, dann ist diese Frage geklärt. Solche Fälle einfach vermeiden. Kommen in der Praxis sowieso selten vor.
 
Genau. Sobald man nämlich bei einer so simplen Anweisung mit Basisoperatoren lange nachdenken muss was denn da jetzt genau passiert macht man in aller Regel (stilistisch) etwas falsch und sollte besser auf eine etwas längere aber klarere Schreibweise zurückgreifen.
So würde ich die Prä-/Postinkrementoperatoren nur dann verwenden, wenn sie für sich stehen und nicht mit anderen arithmetischen Operatoren in einem Ausdruck vermischt werden.
 
Zurück
Oben