+2 Daumen
72 Aufrufe

Ich weiß, dass es schlechter Stil ist so zu programmieren, aber nur aus Interesse her, wieso ergibt sich hierbei die Konstante -2? (Ausprobiert mit Java Eclipse)

int x;
int a = 0;
x = ++a - a++;

Egal was man für a einsetzt, x wird immer -2 ergeben.

Ich hab es als erstes mit dem Beispiel a = 0 ausprobiert.

Ich weiß, dass bei dem Postinkrement a++, der Wert 0 noch in a ist, x zugewiesen wird und danach erst 1 draufaddiert wird und beim Prä-Inkrement ++a, genau umgekehrt, erst der Wert von 0 auf 1 erhöht wird und dann x zu gewiesen wird.

von

Wenn zuerst a++ ausgewertet, dann ++a und dann subtrahiert wird, dann müsste das Ergebnis 2 sein.

2 Antworten

+2 Daumen
 
Beste Antwort
ich meinte x = a++ - ++a

a hat einen Wert A.

  1. Der Minuend wird bestimmt. Dazu wird a++ ausgewertet. Der Minuend ist A. Die Variable a hat jetzt den Wert A+1. In dieser Reihenfolge wegen Postinkrement.
  2. Der Subtrahend wird bestimmt. Dazu wird ++a ausgewertet. Die Variable a hat jetzt den Wert (A+1)+1 = A+2. Das ist auch der Subtrahend. In dieser Reihenfolge wegen Präinkrement.
  3. Die Subtraktion Minuend - Subtrahend wird ausgewertet. A - (A+2) ergibt -2.

Es gibt Programmiersprachen, in denen solche Ausdrücke undefiniertes oder unspezifiertes Verhalten liefern. Dazu gehören C und C++. Ich weiß nicht, ob Java dazugehört.

Undefiniertes Verhalten bedeutet, das Programm darf selbst entscheiden, was und ob es etwas es als Ergebnis der Subtraktion liefert. Das Programm düfte sich also bei jeder Ausführung anders verhalten oder zufällig abstürzen.

Unspezifiziertes Verhalten bedeutet, das das Programm sich zwar immer gleich verhält, aber nicht näher angegeben werden muss, wie dieses Verhalten im Detail aussieht.

In C und C++ kommt es in deinem Ausdruck durch Zusammenwirken von zwei Aspekten zu undefiniertem oder unspezifierten Verhalten:

  • a++ und ++a haben Nebenwirkungen (engl. side effects, eingedeutscht Seiteneffekte). Damit ist gemeint, dass diese zwei Ausdrücke nicht nur einen Wert liefern, sondern darüber hinaus den Zustand des Prozesses ändern (hier: sie ändern den Wert der Variable a).
  • Das Minuszeichen ist kein sogenannter Sequence Point. Ein Sequence Point stellt sicher, dass alle Nebenwirkungen von vorausgehenden Anweisungen schon umgesetzt wurden. Wäre das Minuszeichen ein Sequence Point, dann müsste die Auswertung tatsächlich in der oben angegebenen Reihenfolge passieren. Weil das Minuszeichen in C und C++ kein Sequence Point ist, darf das Programm auch in der Reihenfolge 2. 1. 3. auswerten. Das würde 0 als Ergebnis liefern.
von 1,9 k

Okay danke ich verstehe das jetzt so halb ^^. Aber das erklärt zumindest warum im Debugger bei der ++a '2' steht.

Heißt dass, weil a++ zuerst ausgewertet wird und es am Anfang ja den Wert 0 hat, dieser Wert erst dem x (ich weiß noch nicht wirklich, da das erst noch mit dem rechten Ausdruck verrechnet werden muss, aber so bildlich vorgestellt): wird dieser Wert 0 erstmal beseite gelegt, und die 1 bleibt da. Und weil ++a zuerst ausgewertet wird, also als 1+a. Wird dann die 1 von dem a++ und die 1 vom ++a zu 2 (wie es im Debugger steht) und von der 0 (a++, hat im Debugger den Wert 0) abgezogen. Und dann ergibt sich dadurch die -2.

Zumindest verstehe ich sonst nicht warum ++a im Debugger den Wert 2 am Anfang hat. (die a++ ist logisch, dass das am Anfang 0 ist und danach erst zu 2 wird.)

Im Debugger steht, nach Abschluss der Rechnung (also schon bei der Ausgabe in der Konsole), wenn man über die Variablen hovered, dass a++ am Ende der Rechnung, den Wert 2 hat und ++a den Wert 2. Aber wie gesagt, erst ganz am Schluss.

Danke für die Erklärung !

warum im Debugger

Erst ein mal ein ganz dickes +1 von mir für die Benutzung eines Debuggers.

wird dieser Wert 0 erstmal beseite gelegt,

Ja. Das macht Postinkrement.

und die 1 bleibt da

Genauer gesagt, in der Speicherzelle, auf die mittels der Variablen a zugegriffen werden kann, steht jetzt eine 1.

Und weil ++a zuerst ausgewertet wird

Genauer gesagt, in der Speicherzelle, auf die mittels der Variablen a zugegriffen werden kann, steht nach ++a eine 1+1, also 2 (d. h. aktueller Wert von a plus Inkrement). Außerdem wird nichts "beiseite gelegt", wegen Präinkrement.

Wird dann die 1 von dem a++ und die 1 vom ++a zu 2 (wie es im Debugger steht) und von der 0 ... abgezogen.

Ja.

(a++, hat im Debugger den Wert 0)

Das ist die 0, die "beiseite gelegt" wurde,

Ah. Okay! Danke ich verstehe es jetzt.

steht jetzt eine 1 (früherer Wert) +1, also 2.

genau bei diesem Satz hats Klick gemacht ^^

Okay. Weil wegen dem a++, dass a ja den Wert 1 bekommt aber der Ausdruck selbst 0 ist (weil Postinkrement), und das ++a, dann das vorher zugewiesene a mit der 1 nimmt und nochmal eine 1 draufaddiert und das ganze dann von der 0 abgezogen wird.

(nur nochmal für mich als zusammenfassung)


Und ja den Debugger benutze ich unglaublich gerne. Wenn es den nicht gäbe, gäbe es dutzend mehr Fragen von mir hier in dem Forum ^^ Es erleichtert wirklich vieles. Bin so dankbar, dass sowas eingeführt wurde.

0 Daumen

Hi!

Das ist ein absolut unmögliches Ergebnis. Überprüfe deinen Code.

A wird am Ende den Wert 2 haben, x wird 0 sein.

Weil:

a=0

x = ++a = 1  (a=1)

x -= a++ => 1 - 1++ = 0 (a=1++ = 2)


Probier es gerne mal in einem online Compiler aus. Und natürlich wird es auch ein anderes Ergebnis für x, wenn für a ein anderer Startwert gilt.


Beste Grüße

von

Ach ich bin so blöd...

ich meinte x = a++ - ++a

a = 0;
prtVar("x = a++ - ++a", x = a++ - ++a);

Das war mein Code.

Und danach kam dabei -2 raus.



Bei diesem hier: a = 0;
prtVar("x = a++ - ++a", x = ++a - a++);

hab ich grad ausprobiert und verstehe warum 0 raus kommt.


Danke und Entschuldigung für den Fehler ...

Prima! Dann ist das Rätsel ja gelöst.

Wenn man die Summanden tauscht, kommt selbstverständlich wie Oscar schon andeutete -2 raus.

Ja. Aber wieso ist bei diesem Code -2 eine Konstante?

Weil auch wenn ich für a = 5 oder egal was anderes einsetzte kommt -2 raus.

Das ist irgendwie verwirrend.

Wie gesagt, da kann etwas nicht stimmen. Überprüfe, ob du den Wert wirklich derselben Variable zuweist und ob du diese nicht vorher modifizierst.

Mmh. Ich hab das jetzt viele male wiederholt und auch neues Project gemacht, aber eig. kommt jedes Mal -2 raus.

Meine Mitschüler haben das gleiche raus ^^ aber wissen auch nicht, warum das so ist wie es ist.

Also egal: bei a = 55, a = 10, a = 85 egal welche Zahl, jedes Mal kommt -2 raus. Auch für alle negativen Zahlen, die man für a einsetzt.

Ich frag einfach demnächst nochmal meinen Prof. und gebe dann hier ein kleines Update, vielleicht haben wir alle irgendwas komisches im Code ^^

Ein anderes Problem?

Stell deine Frage

Willkommen bei der Stacklounge! Stell deine Frage sofort und kostenfrei

x
Made by a lovely community