C++ Operatoren Vorrang ausführlich bitte
-
Hallo
Also ich programmiere nun eigentlich schon seit Jahren mit C++ aber jetzt überlege ich doch mal wieder etwas über den Vorrang bei Operatoren. Folgendes:
//Bei Arithmetischen Operatoren völlig klar: int i = 1 + 2 * 3 + 2; //9: nicht erwünschtes Ergebnis (* hat Vorrang) int i = (1 + 2) * (3 + 2); //15: erwünschtes Ergebnis ( () hat Vorrang) bool val1 = true; bool val2 = true; bool val3 = false; //wo soll hier der Vorrang von || und && sein? //Hier wird ja von Links nach Rechts ausgewertet... if(val1 || val2 == true && val3 == true){} //Hier entsteht erst ein Vorrang durch die () also eher eine Gruppe, als Vorrang, oder was jetzt? if((val1 || val2 == true) && val3 == true){} //Genau das gleiche, nur umgekehrt. Also, wo ist hier Vorrang? if(val3 == true && (val1 || val2 == true)){}Bei den Arithmetischen Operatoren verstehe ich durchaus den Sinn des Vorrangs (Mathe like). Sonst gibt es unerwünschte Ergebnisse bei der Zuweisung. Aber speziell bei den Logischen Operatoren (&&, ||) verstehe ich nicht ganz wo da Vorrang besteht? Man macht ihn im Endeffekt ja selber (je nach dem wie man die Operanden setzt).

Und wenn man zwei Operanden gruppiert, spricht man da schon von Vorrang? Für mich bedeutet das eigentlich nur "Beide Operanden ergeben einen Gesamtausdruck (bei || z.B., siehe Beispiel oben) anstatt nur einer davon. Könnte mir das mal einer genauer erläutern?
Und was ich überhaupt nicht verstehe, sind die Vorränge bei allen anderen Operatoren wie:
->, ::, ?, :, etc.
Wie ist da Vorrang zu verstehen? Als if/else Beispiel in Form von ?:, da kann man sowieso nicht :? schreiben. Könnt ihr mir da bitte mal das ganze etwas ausführlicher (mit Beispielen) erläutern? Danke!
-
Es wird nicht von links nach rechts ausgewertet. Es wird immer nach der Reihenfolge der Operatoren vorgegangen. Um deine Beispiele mal durchzugehen:
if(val1 || val2 == true && val3 == true){} // wird ausgewertet als: val1 || ((val2 == true) && (val3 == true)) if((val1 || val2 == true) && val3 == true){} // Wird ausgewertet als (val1 || (val2 == true)) && (val3 == true)) if(val3 == true && (val1 || val2 == true)){} // Wird ausgewertet als ((val3 == true) && (val1 || (val2 == true)))
-
Also nach Stroustrup verhält ist die Stärke der Operatoren so:
1. == - Operator
2. && - Operator
3. || - OperatorSomit wird dein erstes Beispiel so ausgewertet:
if(val1 || val2 == true && val3 == true){}-->
if(val1 || ( ( val2 == true ) && (val3 == true) ) ){}if((val1 || val2 == true) && val3 == true){}-->
if((val1 || (val2 == true) ) && (val3 == true) ){}if(val3 == true && (val1 || val2 == true)){}-->
if( (val3 == true) && (val1 || ( val2 == true) ) ){}Die Klammern werden aber auf jeden Fall einzeln ausgewertet.
Die restlichen Operatoren kannst du auch entweder im Standard nachschlagen, oder im Stroustrup schön einer Liste entnehmen.
(s.130 - 6.2)
-
SeppJ schrieb:
Es wird nicht von links nach rechts ausgewertet. Es wird immer nach der Reihenfolge der Operatoren vorgegangen.
Ja und das ergibt für mich (leserlich) ja dann Links nach Rechts ;). Ich lese den Code (speziell Bedingungen) immer von Links nach Rechts. Ausser bei Zuweisungen, von Rechts nach Links. Insofern stimmt das doch. Eure Beispiele repräsentieren ja genau das was ich auch meinte. Die Klammern die ihr nun eingesetzt habt, verdeutlichen das fürs Auge nur besser. Aber genau so meine ich das ja auch.
Also habe ich die Jahre lang nun keinen mist gelernt. Es spielt keine Rolle ob man zuerst einen || Operator einsetzt oder einen && Operator. Fakt ist, man setzt es so ein wie man es braucht und ausgewertet wird es der Reihe nach. Vorrang Klammern gruppieren Operanden eigentlich nur, um sicherzustellen das dort ein Gesamtausdruck entsteht der dann für den Linken (und vielleicht auch Rechten) Operanden ausschlaggebend ist. Stimmt doch?
Was ist aber mit dem Rest den ich da geschrieben habe? Könnt ihr mir mal bitte ein konkretes Fallbeispiel machen, für den Vorrang von Operatoren wie:
[]
->
::
?:
++Das macht für mich keinen Sinn.
int i = array[67];Wo soll [] hier nun Vorrang haben? Und ausserdem, wo soll der Postfix und Präfix Operator Vorrang haben? Man setzt sich doch den Vorrang selbstständig mit dem Einsatz von Post/Präfix
. Sprich: Wählt man Präfix, ist ja klar das der Wert erst erhöht wird (und somit ++ den Vorrang hat) und dann an den L-Wert zugewiesen wird.
-
vorranger schrieb:
Aber speziell bei den Logischen Operatoren (&&, ||) verstehe ich nicht ganz wo da Vorrang besteht?
Vermutlich die Annahme, die DNF sei häufiger anzutreffen.
http://de.wikipedia.org/wiki/Disjunktive_Normalform
-
vorranger schrieb:
Wo soll [] hier nun Vorrang haben?
c=!a[i];
vorranger schrieb:
Und ausserdem, wo soll der Postfix und Präfix Operator Vorrang haben?
c=++a/2;
-
Hm..
Also ich glaube es geht hier jedem so, dass wenn man dein Beispiel lesen würde, man sofort denkt:
"c wird der Negierende Wert von a mit Element n übergeben". So lese ich zumindest. Da stelle ich mir jetzt die Frage, dass dies bereits der Vorrang ist. Sprich, da [] den Vorrang hat, wird mit dem Operator erstmal der Zeiger des Array gesetzt und ert dann mit dem "!" Operator der Wert negiert. Hab ichs nun? Wenn das so ist, wer von euch macht sich denn überhaupt noch über diese Reihenfolge gedanken? Das ist doch absolute unterbewuste Routine, nicht? Aber sollte ich Recht haben, dann verstehe ich nun die Vorrang zusammenhänge auch mit anderen Beispielen.
-
vorranger schrieb:
Wenn das so ist, wer von euch macht sich denn überhaupt noch über diese Reihenfolge gedanken? Das ist doch absolute unterbewuste Routine, nicht?
Jo.
Und man weiß, wo Gefahren stecken und solcher Codecout << a+=5 << '\n';ist sofort verdächtig.
-
vorranger schrieb:
Sprich, da [] den Vorrang hat, wird mit dem Operator erstmal der Zeiger des Array gesetzt und ert dann mit dem "!" Operator der Wert negiert. Hab ichs nun?
Jup.
Darfst aber nicht in die Falle tapsen, immer das zu lesen, was Du für im Programm sinnvoll hältst.Nach
int i[]={5,10}; int* a=&i[0]; int c;Könnte ich aus die 10 auslesen und den Auslesezeiger erhöhen mit
c=*a++;oder die 5 auslesen und erhöhen mit
c=*a++;Im Zweifelsfall setzt man besser unnütze Klammern.
c=(*a)++;oder
c=*(a++);
-
Alles klar, dann vielen Dank
