Frage zur Auswertungsreihenfolge von Operatoren in einem konkreten Fall
-
Belli schrieb:
Langsam glaube ich, Du willst uns verarschen ...
Ich sehe überhaupt keinen Grund unfreundlich zu werden.
Nochmal:
Die Kurzschlussregel zum && - Operator kennst Du, das lässt sich Deinem Eingangsposting entnehmen. Damit die sinnvoll befolgt werden kann, wird zunächst die linke Seite des Operators ausgewertet. Als Folge der short circuit evaluation ist nun völlig egal, was rechts vom Operator steht, und aus diesem Grund wird das auch nicht mehr ausgewertet.Richtig. Das sagte ich ja auch selbst bereits. Ich sehe nicht, wo meine aufgestellte Faustregel dem widerspricht. Sie impliziert nicht den Abbruch, aber sie ist ja auch nicht auf das konkrete Beispiel bezogen, sondern soll allgemeingültig formuliert sein - eine Faustregel eben. Um auch Abbruchsfälle wie den im vorliegenden Beispiel explizit zu erwähnen, kannst du sie Faustregel gerne noch mit dem Zusatz ", bis entweder alle Ausdrücke ausgewertet wurden oder ein Abbruch erfolgt ist." versehen.
-
Die Klammerung hat nichts mit der Auswertungsreihenfolge zu tun. Nichts. Nochmal: Die Klammerung hat nichts mit der Auswertungsreihenfolge zu tun.
Die Auswertungsreihenfolge ist nicht definiert, der Compiler kann die Ausdrücke so auswerten, wie er möchte. Außer bei &&, || und , (Komma), da wird zuerst der linke, dann der rechte Ausdruck ausgewertet. Die Klammerung hat damit nichts zu tun.Laputzki schrieb:
Anschließend werden die Ausdrücke in genau umgekehrter Reihenfolge ausgewertet.
Demzufolge ist dieser Teil deiner Faustregel falsch.
-
Laputzki schrieb:
Belli schrieb:
Langsam glaube ich, Du willst uns verarschen ...
Ich sehe überhaupt keinen Grund unfreundlich zu werden.
Ich werde nicht unfreundlich, ich hab nur meine Meinung gesagt. Und im Weiteren habe noch einmal versucht, eine Erklärung zu geben.
-
Nathan schrieb:
Die Klammerung hat nichts mit der Auswertungsreihenfolge zu tun. Nichts. Nochmal: Die Klammerung hat nichts mit der Auswertungsreihenfolge zu tun.
Klammerung hat nichts mit Auswertungsreihenfolge zu tun? Häh? Es ist doch gerade der Sinn von Klammern die Auswertungsreihenfolge zu bestimmen. Dafür gibt es die. Oder folgt C hier nicht den Regeln der Mathematik?
-
Laputzki schrieb:
Nathan schrieb:
Die Klammerung hat nichts mit der Auswertungsreihenfolge zu tun. Nichts. Nochmal: Die Klammerung hat nichts mit der Auswertungsreihenfolge zu tun.
Klammerung hat nichts mit Auswertungsreihenfolge zu tun? Häh? Es ist doch gerade der Sinn von Klammern die Auswertungsreihenfolge zu bestimmen. Dafür gibt es die. Oder folgt C hier nicht den Regeln der Mathematik?
Klammern sagen auch in der Mathematik nicht, in welcher Reihenfolge du die Teilausdrücke zu berechnen hast.
(35 + 50) × (32 - 11)
Es ist dem Mathematiker völlig wurscht, ob du zuerst 35+50 oder 32-11 rechnest. Hauptsache beide Teilausdrücke werden vor der Multiplikation berechnet.
Mfg Martin
-
Von geklammerten Teilausdrücken sollte man doch eigentlich davon ausgehen können, daß sie immer von innen nach aussen ausgewertet werden. Ist meiner Erfahrung nach auch so. Die Operatorpräzedenz muß natürlich beachtet werden.
Eine Klammer als Klammer ist erstmal gar kein Operator - den zutreffenden Namen habe ich jetzt nicht dafür - es ist ein Strukturierungshilfsobjekt oder so.Ob der TE so langsam ins trolling gekippt ist traue ich mich nicht zu beurteilen. Eine Meinung dazu hätte ich aber schon.
-
Hallo Martin,
auch dir einen freundlichen Gruß.
mgaeckler schrieb:
Klammern sagen auch in der Mathematik nicht, in welcher Reihenfolge du die Teilausdrücke zu berechnen hast.
(35 + 50) × (32 - 11)
Es ist dem Mathematiker völlig wurscht, ob du zuerst 35+50 oder 32-11 rechnest. Hauptsache beide Teilausdrücke werden vor der Multiplikation berechnet.
Sie werden aber nur vor der Multiplikation berechnet, weil sie in Klammern stehen. Ohne die Klammern würde als Erstes 50 × 32 berechnet. Also beeinflussen die Klammern sehr wohl die Auswertungsreihenfolge.
Dass es in deinem Beispiel egal ist, ob zuerst der rechte oder der linke Teilausdruck berechnet wird, ist klar. Das ist aber auch nicht die Frage, die ich gestellt habe, denn ich weiß ja, dass in C beim &&-Operator zuerst die linke Seite ausgewertet wird.
Meine Frage war ursprünglich eine ganz andere, nämlich warum in dem konkreten Beispiel 1 < 0 && 2 < a++ nicht der ++-Operator vor dem &&-Operator ausgeführt wird, obwohl er ja eine höhere Priorität besitzt.
Nathan schrieb daraufhin, dass die Operatorenpriorität lediglich bestimmt, wo die Klammern sein würden, aber nicht die Auswertungsreihenfolge. DirkB ergänze dazu, dass die Klammerung in meinem Beispiel dann folgendermaßen aussehen würde: (1 < 0) && (2 < (a++)). Ok, dann betrachten wir diesen Fall mal:In der Mathematik ist es so, dass erst die in Klammern stehenden Ausdrücke ausgewertet werden. Demnach müsste bei DirkBs Klammerung a++ [in der Mathematik: a+1] vor (2 < (a++)) und letzteres vor der &&-Verknüpfung stattfinden. (1 < 0) müsste auch vor der &&-Verknüpfung stattfinden, stünde aber in keinem Prioritätenverhältnis zu dem was auf der rechten Seite der &&-Verknüpfung steht. Soweit die Mathematik.
C wertet die &&-Verknüpfung aber offenbar vor dem a++ aus, obwohl a++ in Klammern steht, wogegen die &&-Verknüpfung nicht in Klammern steht. Damit würde C folglich entgegengesetzt der mathematischen Logik auswerten, und das ist das, was ich in meine (zu überprüfende!) Faustregel (+ ihrer späteren Ergänzung) geschrieben habe.
Jetzt ist also aktuell die Frage: Ist Nathans und DirkBs Klammerung korrekt? Dann würde meine auf deren Annahmen beruhende Faustregel stimmen, was ich selbst bezweifle. Oder ist die Klammerung doch nicht die korrekte Antwort auf meine Ursprungsfrage, warum die Auswertung von a++ trotz höherer Operator-Priorität durch die &&-Verknüpfung verhindert wird, also warum nicht a++ als erstes ausgewertet wird? In letzterem Fall wäre ich für weitere Erklärungsversuche dankbar.
Und um es in Anbetracht gegenteiliger Vermutungen von Belli und EOP ganz klar zu sagen: Nein, ich will hier niemanden verarschen, argumentiere hier nach bestem Wissen und Gewissen und bin für jeden eurer Versuche, mir zu helfen, dankbar, auch wenn sich die eine oder andere eurer Aussagen möglicherweise als nicht korrekt herusstellen sollte. Der gute Wille zählt, und den habe auch ich.
-
Laputzki schrieb:
(1 < 0) && (2 < (a++))
[...]
[...] Oder ist die Klammerung doch nicht die korrekte Antwort auf meine Ursprungsfrage, warum die Auswertung von a++ trotz höherer Operator-Priorität durch die &&-Verknüpfung verhindert wird, also warum nicht a++ als erstes ausgewertet wird?Short. Circuit. Evaluation.
-
Laputzki schrieb:
Und um es in Anbetracht gegenteiliger Vermutungen von Belli und EOP ganz klar zu sagen: Nein, ich will hier niemanden verarschen, argumentiere hier nach bestem Wissen und Gewissen und bin für jeden eurer Versuche, mir zu helfen, dankbar, auch wenn sich die eine oder andere eurer Aussagen möglicherweise als nicht korrekt herusstellen sollte. Der gute Wille zählt, und den habe auch ich.
Du machst hier den Eindruck, willst du mit allen Mitteln deine Faustregel zurechtbiegen. Das geht aber nicht, da sie einen falschen Ansatz hat. Auf uns wirkt das, als würdest du unsere Erklärungen ignorieren oder falsch deuten.
Um nochmal auf das Beispiel vomgaeckler zurückzukommen:
mgaeckler schrieb:
(35 + 50) × (32 - 11)
Es gibt 2 mögliche Berechnungsarten:
int a = 35+50; int b = 32-11; int c = a*b;
int a = 32-11; int b = 35+50; int c = a*b;
Beide sind erlaubt. Deine Faustregel lässt aber nur eine Möglichkeit zu.
Es gibt nur 4 Ausnahmen, bei denen die Reihenfolge eindeutig ist: ';', ',', '&&' und '||'.
-
Die Operatoren rangfolge sagt nur aus, wie die Operatoren zu Ihren Operanden in Bezug stehen.
Also 5+2×3 heisst, das der Operator × zu den Operanden 2 und 3 gehört. Der Operator + hat die Operatoren 5 und 2×3. Welche der beiden zuerst in das Register geladen wird bleibt aber dem Compiler überlassen.
move #5, d0
move #3, d1
move #2, d2
mul d2, d1
Add d1, d0Ist ok
Move #2, d0
Move #3, d1
Mul, d1, d0
Move #5, d1
Add, d1, d0Ist auch ok
Wie Du siehst, wurden die drei Operatoren in unterschiedlicher Reihenfolge ausgewertet.
Diese 3 Operatoren könnten wieder Operationen mit eigenen Operatoren enthalten. Deren Reihenfolge ist dann auch entsprechend anders.
Hoffe es ist jetzt klar.
Mfg Martin
-
Darüber hinaus gibt es wohl ein kleines Missverständnis bezüglich dem Begriff der Auswertungsreihenfolge.
Bei so einem Ausdruck: a + b * c ist es natürlich klar, dass zuerst b * c multipliziert werden und dann a addiert. Aber hat man Funktionsaufrufe: a() + b() * c() ist es nicht spezifieziert in welcher Reihenfolge die Funktionen aufgerufen werden. Das meinte ich (und vermutlich andere) hauptsächlich mit Auswertungsreihenfolge.
-
Mach einfach keine so dämlichen Konstrukte wenn du nicht SeppJ's und Swordfish's code obfuscation contest beitreten willst.
In-/Dekremente sind immer mit Vor- und Voraussicht zu benutzen.
Aufgeteilt und eine Zeile mehr geschrieben kann dich vor überraschenden Ergebnissen bewahren.
Ansonsten ist das eine ziemlich überflüssige, konstruierte Geschichte, die eigentlich Keinem hilft.
Interessant wäre vielleicht wie das Ganze mit einem Präfix ausgehen würde.
Bliebe aber immernoch eine ziemlich überflüssige, konstruierte Geschichte, die eigentlich Keinem hilft.
-
EOP schrieb:
Mach einfach keine so dämlichen Konstrukte wenn du nicht SeppJ's und Swordfish's code obfuscation contest beitreten willst.
In-/Dekremente sind immer mit Vor- und Voraussicht zu benutzen.
Die Kurzschlussauswertung in Kombination mit Seiteneffekten auf der rechten Seite ist aber ein Klassiker der (nicht-obskuren) C-Programmierung. Das sollte man schon kennen und auch keine Scheu vor der Benutzung haben. Man kann auch sagen das muss man kennen, denn sonst kommt es schnell zu eben dem Fehler, vor dem du hier warnst. Aber wenn man es sowieso kennt, kann man es ja auch produktiv einsetzen
.
-
SeppJ schrieb:
EOP schrieb:
Mach einfach keine so dämlichen Konstrukte wenn du nicht SeppJ's und Swordfish's code obfuscation contest beitreten willst.
In-/Dekremente sind immer mit Vor- und Voraussicht zu benutzen.
Die Kurzschlussauswertung in Kombination mit Seiteneffekten auf der rechten Seite ist aber ein Klassiker der (nicht-obskuren) C-Programmierung. Das sollte man schon kennen und auch keine Scheu vor der Benutzung haben. Man kann auch sagen das muss man kennen, denn sonst kommt es schnell zu eben dem Fehler, vor dem du hier warnst. Aber wenn man es sowieso kennt, kann man es ja auch produktiv einsetzen
.
Wieso bist du um 3 morgens nicht im Bett, wo du eigentlich hingehörst?
EDIT:
Und - natürlich benutze ich es auch. Ist ja eine der Sachen, die ich an C/C++ ziemlich cool finde.
Aber nicht bei Konstrukten wieif( a < 1 && b < c++ || d > --c & f-- && ~g | --h ^ c )
Muss nicht sein wenn du vorhersagbare Ergebnisse haben willst.
-
Klar, kann man's auch übertreiben.
-
4 morgens und SeppJ sitzt immernoch aufm Wachturm. Unglaublich.
-
EOP schrieb:
4 morgens und SeppJ sitzt immernoch aufm Wachturm. Unglaublich.
Zeit ist relativ.
-
SeppJ schrieb:
Zeit ist relativ.
Für mich anscheinend auch.
-
EOP schrieb:
Mach einfach keine so dämlichen Konstrukte wenn du nicht SeppJ's und Swordfish's code obfuscation contest beitreten willst.
Siehst Sepp was wir angerichtet haben? EOP wird wohl alles obskur anmutende von nun an in die Obfuscation-Ecke stellen
-
Möglicherweise hat es gerade bei mir *klick* gemacht, also hoffe ich, dass ihr mir bestätigen könnt, dass mein folgendes Gedankenspiel korrekt ist:
Gegeben ist: 1 < 0 && 2 < a++
Was macht C nun damit? Nun, zunächst mal halten wir fest, was C damit nicht macht:
Compiler: "Dummdidumm was für ein schöner Morgen...oh was seh ich da? Ein Ausdruck, wie schön! Ich bin jetzt aber noch zu müde, mir sofort den ganzen Ausdruck anzusehen und in Gänze zu interpretieren. Also pick ich mir erstmal nur den Operanden mit der höchsten Priorität raus und guck mir den Rest später an. Na, dann komm her, kleiner Inkrement-Operator. Du zählst jetzt erstmal schön a um 1 hoch. Danke, jetzt darfst du dich wieder setzen. Sodelle, was haben wir noch? Aahhh, einen <-Operator, ein Klassiker! 1 < 0 ?? Unsinn! Setzen, sechs! *kopfschüttel* Wie gehts weiter? Hmm, ein &&-Operator...na, der dürfte von dem Quatsch, der da links von ihm veranstaltet wird aber gar nicht begeistert sein und bricht beleidigt den ganzen Ausdruck ab. Oh, hoppla, dann hätte ich dem Inkrement-Operator ja gar nicht sagen dürfen, dass er um 1 hochzählen soll...jetzt ist's zu spät...wie peinlich..."
Ok, das macht C also nicht. Und was macht es nun wirklich? Folgendes:
Compiler: "Dummdidumm was für ein schöner Morgen...oh was seh ich da? Ein Ausdruck, wie schön! Ich bin zwar noch nicht ganz wach, aber bevor ich hier irgendeinen peinlichen Unsinn anstelle, guck ich mir den Ausdruck lieber erstmal ganz genau von vorne bis hinten in seiner vollem Pracht an, um zu wissen, was der letztendlich im Schilde führt. Du brauchst gar nicht so eifrig zu winken, kleiner Inkrement-Operator. Ich hab dich schon gesehen und weiß, dass du die höchste Priorität hast, du kleiner Angeber. Aber ich guck mir erst noch deine Freunde an, was die so vorhaben. *guck* *amkopfkratz* *grübel* Aha, der &&-Operator wird, wenn ich den Code ausführe, wieder die beleidigte Leberwurst spielen und allen den Spaß versauen. *kopfschüttel* Sorry, kleiner Inkrement-Operator, du hast zwar die höhere Priorität, aber wenn hier eh gleich das Spielbrett vom Tisch gefegt wird, ist es auch überflüssig dich vorher noch a um 1 hochzählen zu lassen. Sei nicht traurig, morgen ist ein neuer Tag."
Ist das so korrekt? Der Compiler analysiert erst den Gesamtausdruck und entscheidet dann, dass der Inkrement-Operator, obwohl seine Priorität höher ist als die des &&-Operators, nicht ausgeführt wird, da der &&-Operator das nachträglich als Fehler entlarfen würde?
EOP schrieb:
Mach einfach keine so dämlichen Konstrukte wenn du nicht SeppJ's und Swordfish's code obfuscation contest beitreten willst.
In-/Dekremente sind immer mit Vor- und Voraussicht zu benutzen.
Aufgeteilt und eine Zeile mehr geschrieben kann dich vor überraschenden Ergebnissen bewahren.
Ansonsten ist das eine ziemlich überflüssige, konstruierte Geschichte, die eigentlich Keinem hilft.
Da stimme ich dir voll und ganz zu. Ich selbst würde das auch so nicht schreiben. Ich will aber darauf vorbereitet sein, sowas in der anstehenden Klausur richtig lösen zu können. In den vom gleichen Proffessor gestellten Übungen kam der In-/Dekrement-Operator dran und sorgte bei den meisten für reichlich Verwirrung.
EOP schrieb:
Interessant wäre vielleicht wie das Ganze mit einem Präfix ausgehen würde.
Jemand 'ne Idee?