frage zu if(bed1&&bed2&&bed3&&bed4&&..)
-
nur um sicher zu gehen
wenn ich mehrere bedingngen mit und verknüpfe
if(bed1&&bed2&&bed3&&bed4&&..)
wird dann falls bed1 nicht erfüllt ist abgebrochen oder werden erst alle bedingungen geprüft?benutze den compiler von VS 2003.NET
-
Falls irgendeine Bedingung falsch ist wird nicht weiter ausgewertet. Hat auch nichts mit dem Compiler sondern der Sprache zu tun.
-
finix schrieb:
Falls irgendeine Bedingung falsch ist wird nicht weiter ausgewertet. Hat auch nichts mit dem Compiler sondern der Sprache zu tun.
Stimmt das wirklich? Ich hatte mal einen angeblich ANSI- C- Compiler, der einen Ausdruck
if(funktion1()&&funktion2()&&funktion3())
wirklich erst nach Abrattern aller Funktionen aufgelöst hat.
Ein anderer Compiler fängt ulkigerweise mit funktion3 an, aber auch nur, wenn man die höchste Optimierungsstufe einstellt.
Gibt es da für ANSI wirklich verbindliche Vorgaben?
Btw, Keil- C für 8051 schert sich heute noch einen feuchten Kehricht um "volatile" ...
auch angeblich ANSI- C
... wie gesagt, angeblich ...
-
pointercrash() schrieb:
finix schrieb:
Falls irgendeine Bedingung falsch ist wird nicht weiter ausgewertet. Hat auch nichts mit dem Compiler sondern der Sprache zu tun.
Stimmt das wirklich?
Ja, das stimmt. Allerdings gilt wieder die as-if-Regel: Solange sich am Ergebnis nichts ändert, darf der Compiler alles machen, wozu er lustig ist. D.h.:
Ein anderer Compiler fängt ulkigerweise mit funktion3 an, aber auch nur, wenn man die höchste Optimierungsstufe einstellt.
Solange funktion3 keine Seiteneffekte hat, ist das vollkommen legitim.
-
SG1 schrieb:
Ja, das stimmt. Allerdings gilt wieder die as-if-Regel: Solange sich am Ergebnis nichts ändert, darf der Compiler alles machen, wozu er lustig ist. D.h.:
Nochmal blöd nachgefragt:
Um ein multiples AND aufzulösen, wird mindestens eine Funktion ausgeführt, welche ist egal? Ich habe mich mal darauf verlassen, daß es von links nach rechts geht und bin aus o.a. Gründen böse auf die Nase gefallen. Bei einer Portierung eines Busprotokolls gab es eine Zeile:if (send_initiator()&&get_sync()&&send_message()&&send_terminator()) printf("Message erfolgreich versendet");
Und es macht schon einen Unterschied, ob der Terminator zuerst gesendet wird
oder zuletzt
Ist da ANSI wirklich unverbindlich?
-
SG1 schrieb:
Ein anderer Compiler fängt ulkigerweise mit funktion3 an, aber auch nur, wenn man die höchste Optimierungsstufe einstellt.
Solange funktion3 keine Seiteneffekte hat, ist das vollkommen legitim.
Naja, eigentlich nicht. Der Standard garantiert left-to-right evaluation. Zudem werden keine nachfolgenden Operanden ausgewertet, sobald einer false ist.
-
groovemaster schrieb:
SG1 schrieb:
Ein anderer Compiler fängt ulkigerweise mit funktion3 an, aber auch nur, wenn man die höchste Optimierungsstufe einstellt.
Solange funktion3 keine Seiteneffekte hat, ist das vollkommen legitim.
Naja, eigentlich nicht. Der Standard garantiert left-to-right evaluation. Zudem werden keine nachfolgenden Operanden ausgewertet, sobald einer false ist.
ich hoffe, das kann nochmal jemand bestätigen.. wäre ja furchtbar wenn die Reihenfolge da willkürlich ist
da hätte ich jetzt eine Menge quelltext zu korrigieren
-
DrGreenthumb schrieb:
ich hoffe, das kann nochmal jemand bestätigen.. wäre ja furchtbar wenn die Reihenfolge da willkürlich ist
da hätte ich jetzt eine Menge quelltext zu korrigieren
Für &&, ||, ?: und , ist die Auswertungsreihenfolge genau definiert wie groovemaster schon gesagt hat.
-
Also erstmal zur Ursprungsfrage: Ja, es ist durch den Standard abgedeckt, dass man das so macht.
Ja, das stimmt. Allerdings gilt wieder die as-if-Regel: Solange sich am Ergebnis nichts ändert, darf der Compiler alles machen, wozu er lustig ist. D.h.: Solange funktion3 keine Seiteneffekte hat, ist das vollkommen legitim.
Diese Aussage war wohl eher verwirrend als nützlich. Sie stimmt zwar, aber die Funktionen vom Originalposter haben wohl Nebeneffekte, sonst wäre es ihm ja egal, ob sie ausgeführt werden oder nicht.
-
_gast schrieb:
Nur um sicher zu gehen:
wenn ich mehrere Bedingungen mit && verknüpfeif (bed1 && bed2 && bed3 && bed4 && ..)
wird dann, falls bed1 nicht erfüllt ist, abgebrochen,
oder werden erst alle Bedingungen geprüft?Der Standard legt fest, dass dann abgebrochen wird:
Unlike the bitwise binary & operator, the && operator
guarantees left-to-right evaluation; there is a sequence
point after the evaluation of the first operand. If the
first operand compares equal to 0, the second operand is not
evaluated.Die Steve Summits C-FAQ stellt das auch nochmal klar:
There is a special "short-circuiting" exception for these
operators: the right-hand side is not evaluated if the left-hand
side determines the outcome (i.e. is true for || or false for
&&). Therefore, left-to-right evaluation is guaranteed, as it
also is for the comma operator.
-
Ringding schrieb:
[...] Allerdings gilt wieder die as-if-Regel: Solange sich am Ergebnis nichts ändert, darf der Compiler alles machen, wozu er lustig ist. D.h.: Solange funktion3 keine Seiteneffekte hat, ist das vollkommen legitim.
Diese Aussage war wohl eher verwirrend als nützlich. Sie stimmt zwar, aber die Funktionen vom Originalposter haben wohl Nebeneffekte, sonst wäre es ihm ja egal, ob sie ausgeführt werden oder nicht.
Also ich kann Dir da nicht zustimmen, wenn Du sagst "[diese Aussage] stimmt zwar, aber...", denn sie stimmt definitiv nicht. (Siehe mein anderes Posting.)
-
man kann sich aber nicht darauf verlassen, dass alle compiler standardkonform arbeiten
ich hatte vor kurzem einen (imagecraft icc12) der konnte noch nicht mal das:array[variable++] = irgendwas;
er hat falschen maschinencode erzeugt, der in einigen fällen zum absturz führte.
musste man echt so schreibenarray[variable] = irgendwas; variable++;
-
net schrieb:
man kann sich aber nicht darauf verlassen, dass alle compiler standardkonform arbeiten
Minderwertige Compiler gibt es leider
vorallem im embedded bereich gibt es da einige hacks. Wo scheinbar ein bestehender Compiler einfach auf diesen Prozessor umgemodelt wurde und dabei die optimierungen etwas brutal sind
idr hilft es dann aber, mit weniger optimierungen zu kompilieren und/oder komplizierte konstrukte zu vermeiden.
i++ ist in der Tat oft ein Problem wenn es innerhalb eines komplexen statements steht.
da hat man es am Desktop natürlich viel besser, da setzt sich so ein Compiler nämlich garnicht erst durch
-
EinGast schrieb:
Also ich kann Dir da nicht zustimmen, wenn Du sagst "[diese Aussage] stimmt zwar, aber...", denn sie stimmt definitiv nicht. (Siehe mein anderes Posting.)
Doch, sie stimmt.
bool inline einpraedikat(double x) { return sin(x) > .1; } [...] if (<bedingung> && einpraedikat(x)) { dosomething(); }
Nehmen wir an, dass der Compiler "sin" als eingebaute Funktion erkennt (was er darf). Weil sin besonders lange rechnet, möchte es der Compiler vielleicht möglichst weit nach vorne schieben. Daher schiebt er es einfach vor die Auswertung von <bedingung>. Du wirst nie etwas davon merken, ob einpraedikat(x) nun ausgerechnet wurde oder nicht, weil einpraedikat keine Nebeneffekte hat.
-
Shade Of Mine schrieb:
Wo scheinbar ein bestehender Compiler einfach auf diesen Prozessor umgemodelt wurde....
in dem fall haben die den lcc ( http://www.cs.princeton.edu/software/lcc/ ) als basis genommen
-
Ringding schrieb:
EinGast schrieb:
Also ich kann Dir da nicht zustimmen, wenn Du sagst "[diese Aussage] stimmt zwar, aber...", denn sie stimmt definitiv nicht. (Siehe mein anderes Posting.)
Doch, sie stimmt.
bool inline einpraedikat(double x) { return sin(x) > .1; } [...] if (<bedingung> && einpraedikat(x)) { dosomething(); }
Nehmen wir an, dass der Compiler "sin" als eingebaute Funktion erkennt (was er darf). Weil sin besonders lange rechnet, möchte es der Compiler vielleicht möglichst weit nach vorne schieben. Daher schiebt er es einfach vor die Auswertung von <bedingung>. Du wirst nie etwas davon merken, ob einpraedikat(x) nun ausgerechnet wurde oder nicht, weil einpraedikat keine Nebeneffekte hat.
nun sieh dir folgenden Code an, auch 2 "Funktionen" ganz ohne Nebeneffekte:
if( pointer && *pointer == x ) ...
Das wäre ja furchtbar, wenn der Compiler hier den Zugriff auf *pointer nach vorne nähme.
-
Ringding schrieb:
EinGast schrieb:
Also ich kann Dir da nicht zustimmen, wenn Du sagst "[diese Aussage] stimmt zwar, aber...", denn sie stimmt definitiv nicht. (Siehe mein anderes Posting.)
Doch, sie stimmt.
*Seufz* Nein sie stimmt nicht. Ich denke, der C-Standard ist in diesem Fall wohl die verbindlichere Informationsquelle, als Deine (in diesem Fall eher unmaßgebliche) persönliche Meinung, meinst Du nicht auch?
(eod)
-
DrGreenthumb schrieb:
Das wäre ja furchtbar, wenn der Compiler hier den Zugriff auf *pointer nach vorne nähme.
Ja. Vielleicht noch klarer:
int function(int x) { int y = 1/x; return 1; } [...] if ((x != 0) && function(x)) { ... }
Der Compiler kann doch unmöglich wissen, w a s die Funktion denn nun für jeden x-Wert tut oder nicht tut. Für x = 0 hat die Funktion aber einen etwas unschönen "Seiteneffekt".
(Natürlich könnte in der Funktion auch ein Pointer involviert sein, oder was auch immer.)
-
@DrGreenthumb: gutes Argument, aber der Compiler "weiß" ja, dass ein Pointerzugriff gefährlich sein kann, und dass er ihn deshalb nicht vorziehen darf. Der Compiler weiß auch, dass eine Division gefährlich ist.
Konsultieren wir den C99-Draft (was anderes hab ich gerade nicht hier, es wird aber nicht wesentlich anders sein):
An implementation might define a one-to-one correspondence between abstract and actual semantics: at every sequence point, the values of the actual objects would agree with those specified by the abstract semantics.
Alternatively, an implementation might perform various optimizations within each translation unit, such that the actual semantics would agree with the abstract semantics only when making function calls across translation unit boundaries. In such an implementation, at the time of each function entry and function return where the calling function and the called function are in different translation units, the values of all externally linked objects and of all objects accessible via pointers therein would agree with the abstract semantics. Furthermore, at the time of each such function entry the values of the parameters of the called function and of all objects accessible via pointers therein would agree with the abstract semantics. In this type of implementation, objects referred to by interrupt service routines activated by the signal function would require explicit specification of volatile storage, as well as other implementation-defined restrictions.Also im Prinzip darf der Compiler machen, was er will, solange sich das Programm so verhält, wie es durch den Standard festgelegt wird.
-
Hierzu auch nocheinmal etwas aus deutschsprachigen Übersetzung von Steve Summits C-FAQ:
4.4: Kann ich die Reihenfolge, in der Teilausdrücke ausgewertet werden,
nicht durch Klammern festlegen? Selbst ohne Klammern sollte die
Reihenfolge doch durch die Rangfolge der Operatoren vorgeschrieben
sein.A: Die Hierarchie der Operatoren und Klammern legen nur zum Teil fest,
in welcher Reihenfolge die Teilausdrücke ausgewertet werden. Im
Beispielf() + g() * h()
ist nur sicher, dass die Multiplikation vor der Addition ausgeführt
wird. Welche der drei Funktionen zuerst aufgerufen wird, ist
allerdings undefiniert.Wenn die Reihenfolge, in der Teilausdrücke ausgewertet werden,
wichtig ist, führt an temporären Variablen kein Weg vorbei.4.5: Und wie steht es mit den &&-, ||- und Komma-Operatoren? Ich sehe
häufiger Ausdrücke der Formif((c = getchar()) == EOF || c == '\n') ...
A: Für diese Operatoren (sowie für den ?:-Operator) gilt tatsächlich
eine Ausnahme; Jeder einzelne dieser Operatoren stellt einen
"sequence point" dar (d.h. der Ausdruck wird von links nach rechts
ausgewertet). Dies sollte in jedem C-Buch klargestellt werden.Siehe hierzu: K&R I Abschn. 2.6 S. 38, Abschn. A7.11-12 S. 190-191;
K&R II Abschn. 2.6 S. 41, Abschn. A7.14-15 S. 207-208;
ANSI Abschn. 3.3.13 S. 52, 3.3.14 S. 52, 3.3.15 S. 53, 3.3.17 S.55;
CT&P Abschnitt 3.7 Seiten 46-47