Operation mit Seiteneffekt in einem return-Ausdruck
-
Der Wert
valist undefiniert, sofern C++ keine strikte Auswertungsreihenfolge von Links nach Rechts vorschreibt. Vermeide solchen Code!
-
Skym0sh0 schrieb:
1...
Nein. Undefiniert.
edit: Man sollte noch dazu sagen: Das Ergebnis ist nicht aus dem Grund undefiniert, den Gugelmoser meint. Bei Verlassen einer Funktion sind sämtliche Seiteneffekte garantiert ausgewertet. Was hier undefiniert ist, ist ob zuerst i oder zuerst fkt(i) ausgewertet wird.
-
SeppJ schrieb:
Bei Verlassen einer Funktion sind sämtliche Seiteneffekte garantiert ausgewertet.
Darauf wollte ich hinaus, und damit ist die Frage beantwortet.

SeppJ schrieb:
Was hier undefiniert ist, ist ob zuerst i oder zuerst fkt(i) ausgewertet wird.
Hmm, ich dachte fkt(i) würde garantiert zuerst ausgewertet werden, weil ein Funktionsaufruf in der Prioritätenliste weiter oben steht, als die Addition. Wieso wird die Priorität hierbei nicht beachtet?
-
Gugelmoser schrieb:
Wieso wird die Priorität hierbei nicht beachtet?
Priorität ist nur, wierum unsichtbare Klammen stehen.
Das beeinflußt NICHT die zeitliche Auswertungsreihenfolge.
x=a()+b()*c();
Hier wird vielleicht zuerst a, dann c und dann erst b aufgerufen und die Ergebnisse zwischengepeichert. Zeitliche Reihenfolge undefiniert.
Und dann wird das * vor dem + ausgeführt. Prioritäten definiert.
-
volkard schrieb:
Gugelmoser schrieb:
Wieso wird die Priorität hierbei nicht beachtet?
Priorität ist nur, wierum unsichtbare Klammen stehen.
Das beeinflußt NICHT die zeitliche Auswertungsreihenfolge.
x=a()+b()*c();
Hier wird vielleicht zuerst a, dann c und dann erst b aufgerufen und die Ergebnisse zwischengepeichert. Zeitliche Reihenfolge undefiniert.
Und dann wird das * vor dem + ausgeführt. Prioritäten definiert.Ich verstehe es immer noch nicht ganz. Wo kommt z.B. die Priorität des Funktionsaufrufes jemals zum Tragen?
Gibt es dazu eine allgemeine Regel, dass man nicht in eine Falle tappt (bzgl. Seiteneffekt und Auswertungsreihenfolge)?
-
Gugelmoser schrieb:
Gibt es dazu eine allgemeine Regel, dass man nicht in eine Falle tappt (bzgl. Seiteneffekt und Auswertungsreihenfolge)?
Ja. Sequenzpunkte/sequence points. C++ Standard Kapitel 1.9 wird das sogar recht verständlich erklärt, was das genau bedeutet und wo die sind.
-
Gugelmoser schrieb:
Wo kommt z.B. die Priorität des Funktionsaufrufes jemals zum Tragen?
cout<<sin(5);
ist
cout<<(sin(5))
und nicht
(cout<<sin)(5)oder
#include <iostream> #include <cmath> using namespace std; double hello() { cout<<"hello"; return 5; } double world() { cout<<"world"; return 3; } int main() { typedef double funcType(); funcType* h=&hello; funcType* w=&world; //cout<<*h()<<'\n';//Klappt nicht, denn () bindet stärker als *. cout<<(*h)()<<'\n';//Klappt. cout<<(*h)()+(*w)()<<'\n';//Zufällig wird h vor w aufgerufen, Glück gehabt. cout<<pow((*h)(),(*w)())<<'\n';//Und jetzt andersrum. return 0; }Ausgabe bei mir:
hello5 helloworld8 worldhello125
-
Noch kurz eine off-topic Frage:
Bedeutet undefined behavior, dass wirklich alles passieren könnte, dass ich bei folgendem
i = i++ - 1;auch ein Bluescreen bekommen könnte?
-
Bei Undefined Behaviour darf alles passieren. Hier hast du aber einen Fall von Unspecified Behaviour.
-
Michael E. schrieb:
Bei Undefined Behaviour darf alles passieren. Hier hast du aber einen Fall von Unspecified Behaviour.
Um ehrlich zu sein, das hab ich auch gedacht. Aber dann hab ich gesehen, dass es im Draft (n3242) als Undefined Behaviour bezeichnet wird. [in früheren Drafts stand noch Unspecified Behaviour dran.]
-
Gugelmoser schrieb:
Michael E. schrieb:
Bei Undefined Behaviour darf alles passieren. Hier hast du aber einen Fall von Unspecified Behaviour.
Um ehrlich zu sein, das hab ich auch gedacht. Aber dann hab ich gesehen, dass es im Draft (n3242) als Undefined Behaviour bezeichnet wird.
Kapitelnummer? n3242 ist ja nicht der letzte Draft gewesen...
-
pumuckl schrieb:
Gugelmoser schrieb:
Michael E. schrieb:
Bei Undefined Behaviour darf alles passieren. Hier hast du aber einen Fall von Unspecified Behaviour.
Um ehrlich zu sein, das hab ich auch gedacht. Aber dann hab ich gesehen, dass es im Draft (n3242) als Undefined Behaviour bezeichnet wird.
Kapitelnummer? n3242 ist ja nicht der letzte Draft gewesen...
Kapitel 1.9, Absatz 15.
-
Gugelmoser schrieb:
Kapitel 1.9, Absatz 15.
Undefined auch in n3291
-
Beispiele sind bekanntlich nicht normativ, der relevante Satz steht aber direkt davor:
If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.
"sequenced after" ist transitiv.
Der Seiteneffekt der Zuweisung wird nach der Wertberechung des Ausdrucks i++ - 1 sequenziert, welche wiederum nach der Wertberechnung von i++ sequenziert wird. Es besteht aber keine Sequenzierung zwischen der Wertberechnung von i++ und dem Seiteneffekt, der Erhöhung des Wertes, der in i gespeichert ist. Eine Sequenzierung der Seiteneffekte findet auch nicht aus anderen Gründen statt. Damit resultiert UB.
-
Hier ein kleiner Quiz: bestimme den Wert des Ausdruckes und den der Variable i (unabhängig voneinander, i sei also immer 0 vor der Auswertung jedes einzelnen Ausdruckes). Im Falle von unspezifiziertem Verhalten sind alle möglichen Ergebnisse gefragt.
int& foo(int& v) { return ++v; } int i = 0; i + i; // (1) ++i + i; // (2) i++ + i; // (3) i = ++i; // (4) foo(i) + i; // (5) foo(i) + i++; // (6) foo(++i) + i; // (7) foo(++i) + i++; // (8) foo(foo(i)) + i; // (9) foo(++i) + foo(++i);// (10)Lösung gibts später (bei Interesse).
-
camper schrieb:
Lösung gibts später (bei Interesse).
Also ich habe natürlich Interesse.

-
Frage: zählt die Auswertung des Ausdrucks
ials "value computation"?
(Falls ja, hab ich 9x UB)
-
pumuckl schrieb:
Frage: zählt die Auswertung des Ausdrucks
ials "value computation"?
(Falls ja, hab ich 9x UB)Die Bestimmung des Wertes einer Variablen in einem primären Ausdruck (als Folge einer l-zu-rvalue-Konvertierung) ist auch eine "value computation", allerdings sind das ein bisschen zu viele UBs. Ich denke wir können 1-4 abhacken, (1) ist trivial, 2-4 UB (4 ist evtl. bloß unspezifiziert).
Bei 5-10 sind nicht alle undefiniert.
-
camper schrieb:
Bei 5-10 sind nicht alle undefiniert.
Aber man kann sich doch gar nicht sicher sein, ob zuerst der rechte oder der linke Ausdruck ausgewertet wird.
-
Gugelmoser schrieb:
Aber man kann sich doch gar nicht sicher sein, ob zuerst der rechte oder der linke Ausdruck ausgewertet wird.
Ja, aber z.B. (5) ist nicht undefiniert, sondern nicht spezifiziert (hoffe ich mal ;)), weil ein Sequenzpunkt zwischen ++i und i liegt.