Hallo Forum, bin gerade am C lernen. Was mir nicht klar ist: Ist if(a==b+5) das Gleiche wie if(a==(b+5)) Ich habe gesehen, dass es bei den Operatoren Prioritäten gibt, werde aber nicht recht schlau daraus. Danke für Eure Antworten Jens
jens D. schrieb: > Ich habe gesehen, dass es bei den Operatoren Prioritäten gibt, werde > aber nicht recht schlau daraus. Ja, gibt es. Auswendig lernen oder bei Bedarf nachschlagen: http://en.cppreference.com/w/c/language/operator_precedence + bindet stärker als ==
>if(a==b+5) >das Gleiche wie >if(a==(b+5)) Nein. Ist nicht das selbe. Der Unterschied ist: bei 1) muss man nachschlagen oder im Forum fragen. bei 2) isses klar. Ich will damit sagen, dass die der Code nicht nur für den Compiler lesbar sein soll, sondern auch für Biomasse. Wenn es also nicht klar sein sollte: Klammern setzen.
Bildformator schrieb: > Ich will damit sagen, dass die der Code nicht nur für den Compiler > lesbar sein soll, sondern auch für Biomasse. > Wenn es also nicht klar sein sollte: Klammern setzen. naja, der der den code geschrieben hat wird wohl wissen wie es funktioniert, sonst hätte er ihn nicht so geschrieben. Oder willst du das jeder der code so schreibt das ihn jeder Anfänger auch versteht?
Bildformator schrieb: > Ich will damit sagen, dass die der Code nicht nur für den Compiler > lesbar sein soll, sondern auch für Biomasse. > Wenn es also nicht klar sein sollte: Klammern setzen. Das man nicht alle Precedence Stufen im Kopf auswendig parat hat, gestehe ich dir gerne zu. Aber zumindest die wichtigsten sollte man schon kennen. Zumal die so angeordnet sind, dass sich die übliche und intuitiv richtige Reihung ergibt. Wenn eine Programmiersprache so definiert wäre, dass ein (sinngemässses)
1 | if( a+b == c+d ) |
implizit als
1 | if( a + (b==c) + d ) |
geparst werden würde, dann würden sich viele Programmierer wohl mächtig wundern. In allen Programmiersprachen, die ich kenne, haben Vergleichsoperatoren eine geringere Priorität als arithmetische Operatoren. Und das ist auch gut so.
:
Bearbeitet durch User
@ Karl Heinz (kbuchegg) (Moderator) >Das man nicht alle Precedence Stufen im Kopf auswendig parat hat, >gestehe ich dir gerne zu. Aber zumindest die wichtigsten sollte man >schon kennen. So ziemlich jedes der C-Standardwerke hat die auf den letzten Seiten drin, ein Griff ins Regal, alles im Blick.
jens D. schrieb: > Ich habe gesehen, dass es bei den Operatoren Prioritäten gibt, werde > aber nicht recht schlau daraus. Was genau ist dir nicht klar? Die Prioritätstabelle (bspw. die oben von Hannes verlinkte) ist folgendermaßen anzuwenden: Angenommen, du hast den Ausdruck A op1 B op2 C A, B, C sind dabei die Operanden (z.b. Zahlen oder Variablen), op1 und op2 sind Operatoren (z.B. +, *, == oder =). Um herauszufinden, wie der Ausdruck ausgewertet wird, suchst du die beiden Operatoren in der Tabelle. Jetzt gibt es drei Möglichkeiten: 1. op1 steht in der Tabelle höher als op2 (in der Spalte "Precedence" steht für op1 eine kleinere Zahl): Dann hat op1 höhere Priorität und der Ausdruck wird ausgewertet wie (A op1 B) op2 C 2. op1 steht in der Tabelle tiefer als op2 (in der Spalte "Precedence" steht für op1 eine größere Zahl): Dann hat op1 niedrigere Priorität und der Ausdruck wird ausgewertet wie A op1 (B op2 C) 3. op1 und op2 stehen stehen im gleichen Feld in der Tabelle: Dann haben beide Operatoren die gleiche Priorität. Wie der Ausdruck ausgewertet wird, entscheidet sich anhand der Spalte "Associativity": a) Ist die Associativity "Left-to-right" (linksassoziativ), wird der Ausdruck ausgewertet wie (A op1 B) op2 C b) Ist die Associativity "Right-to-left" (rechtsassoziativ), wird der Ausdruck ausgewertet wie A op1 (B op2 C) Bei den unären Operatoren verhält es sich ähnlich, nur dass dort entweder der erste oder der zweite Operand fehlt. Beispiele: 1. a==b+5 + hat höhere Priorität als ==, also ist der Ausdruck gleich a==(b+5) 2. *p++ ++ hat eine höhere Priorität als *, also ist der Ausdruck gleich *(p++) 3. a-b+c - und + haben die gleiche Priorität. Da sie linksassoziativ sind, ist der Ausdruck gleich (a-b)+c 4. a=b+=5 = und += haben die gleiche Priorität. Da sie rechtsassoziativ sind, ist der Ausdruck gleich a=(b+=5) d.h. erst wird zur Variablen b der Wert 5 addiert und der neue Wert von b auch a zugewiesen. Hier sind noch ein paar Tipps dafür, wo man sinnvollerweise Klammern setzt (auch wenn sie nicht unbedingt benötigt werden), und wo besser nicht. Natürlich gehen hier die Meinungen teilweise stark auseinander. Anfänger neigen eher dazu, mehr Klammern als nötig zu setzen, während Hardcore-C-Programmieren gerne auf jede überflüssige Klammer verzichten. Man kann die C-Operatoren grob in folgende Gruppen unterteilen: 1. Unäre Suffix-Operatoren (Precedence 1 in der Tabelle) 2. Unäre Präfix-Operatoren (Precedence 2 in der Tabelle) 3. Binäre Rechenoperatoren (Precedence 3, 4 und 5 in der Tabelle) 4. Vergleichsoperatoren (Precedence 6 und 7 in der Tabelle) 5. Binäre Logikoperatoren (Precedence 11 und 12 in der Tabelle) 6. Zuweisungsoperatoren (Precedence 14 in der Tabelle) Die Rangfolge der ersten beiden Gruppen (unäre Operatoren) sollte man sich einfach merken, um nicht zu viele Klammern setzen zu müssen. In präfixop A suffixop liegt die implizite Klammerung immer auf der rechten Seite, also präfixop (A suffixop) Die Rangfolge der Gruppen 2 bis 5 entspricht der Intuition bzw. der Formelnotation aus der Schulmathematik. Da Zuweisungen i.Allg. nur in der obersten Ebene eines Ausdrucks (und nicht in Teilausdrücken) auftauchen, entspricht auch hier die prioritätsmäßige Einordnung der Intuition. Man kann also in einem Ausdruck, dessen Operatoren aus unterschiedlichen Gruppen stammen, optionale Klammern getrost weglassen. Innerhalb der Gruppe 3 (Rechenoperatoren) gilt die ebenfalls aus der Schulmathematik bekannte Punkt-vor-Strich-Regel. Auch innerhalb Gruppe 5 (binäre Logikoperatoren) wird wird von den meisten Leuten die Konjunktion (&&) als stärker bindend als die Disjunktion (||) angesehen, da die Konjunktion eine gewisse Verwandtschaft zur Multiplikation und die Disjunktion zur Addition hat. In den vorgenannten Fällen sollte man meiner Meinung nach nur dann Klammern zu setzen, wenn die Auswertung von der vorgegebenen Rangfolge abweiche soll. Ausdrücke wie a = b + 5 * c a >= 0 && a <= 9 -array[5] *b++ brauchen somit keine Klammerung. Bei b == 0 || a >= 0 && a <= 9 lasse ich normalerweise die Klammern weg, wenn der gesamte Ausdruck nicht zu lang ist. Die Klammerung des rechten Teilausdrucks ist aber ebenfalls in Ordnung, weil der Vorrang von && gegenüber || nicht jedem geläufig ist: b == 0 || (a >= 0 && a <= 9) Werden Shift-Operationen (<< und >>) mit anderen Rechenoperationen gemischt, dürfen gerne Klammern gesetzt werden, da die Shift-Operationen nicht Bestandteil der Schulmathematik sind und es somit keine allgemein anerkannte Rangfolge gibt. Je nachdem, was genau berechnet werden soll, wird man also entweder a << (i + 1) oder (a << i) + 1 schreiben, auch wenn im ersten Fall die Klammern nicht unbedingt erforderlich sind. Ein paar der Operatoren in der Tabelle tauchen in der obigen Gruppenbildung nicht aufund werden hier gesondert behandelt: Da sind als erstes die bitweisen Operatoren (&, ^ und |). Sie sind streng genommen Rechenoperatoren, da sie beliebige Integer-Zahlen als Ergebnis liefern können. Folglich müssten sie prioritätsmäßig bei den Operatoren aus Gruppe 3 (*, + usw.) liegen. Aus historischen Gründen liegen sie aber bei den Logikoperatoren (&& und ||) und damit unterhalb von den Vergleichsoperatoren, was ziemlich ungeschickt ist. Oft will man nämlich das Ergebnis einer Bitoperation (Maskierung) mit einem Wert vergleichen und würde dazu intuitiv schreiben: byte & 0x0f < 3 Das liest der Compiler aber als byte & (0x0f < 3) was ein ziemlich unsinniger Ausdruck ist, den man in dieser Form wohl extrem selten bis überhaupt nie brauchen wird. Stattdessen muss man hier dummerweise explizite Klammern setzen, um das gewünschte Ergebnis zu erhalten: (byte & 0x0f) < 3 Ein weiterer der ungruppierten Kandidaten ist der Operator für bedingte Auswertung (?:, auch ternären Operator genannt, weil er als einziger der C-Operatoren drei Operanden hat). Da er nur selten, und so gut wie nie verschachtelt zum Einsatz kommt, ist es in Ordnung, seine drei Operanden jeweils zu klammern: (a > 0) ? (b + 5) : (c - 5) Dann gibt es noch den Komma-Operator, der ebenfalls nur selten gebraucht wqird. Da er von allen Operatoren die niedrigste Priorität hat und er so gut wie nie in Teilausdrücken auftaucht, muss man bei seiner Verwendung normalerweise keine zusätzlichen Klammern setzen. Bei Klammern, die nur der besseren Lesbarkeit dienen, kann man überlegen, ob nicht ein geschicktes Einfügen oder Weglassen von Leerzeichen den gleichen Zweck erfüllt. In der Mikrocontrollerei hat man oft den Fall, dass man mehrere Bits (z.B. Bit 2, 4 und 5) eines Hardwareregisters setzen und den Rest löschen möchte möchte. Man kann dies mit HWREG = 0x34; tun, allerdings sieht der Leser dabei nicht ohne Weiteres die Nummern der gesetzten Bits. Oft besser ist deswegen HWREG = (1 << 2) | (1 << 4) | (1 << 5); Die Klammern sind hier optional, aber wegen der in der Schulmathematik nicht geläufigen Operatoren empfehlenswert. Man kann aber die Klammern auch weglassen und dabei die Lesbarkeit durch Zusammenrücken der drei Teilausdrücke wiederherstellen: HWREG = 1<<2 | 1<<4 | 1<<5; Die 1<<n-Ausdrücke sind in der hardwarenahen Programmierung ein so gängiges Muster, dass sie ein etwas geübterer Programmierer nicht mehr als Ausdrücke, sondern als Literale mit der Bedeutung "Bit n" sieht. Deswegen halte ich es hier für angebracht, die Leerzeichen vor und nach dem << wegzulassen. Gleichzeitig werden dadurch die Prioritäten der beteiligten Operatoren klar herausgestellt, weswegen man auf die Klammern verzichten kann. Schließlich wird dadurch der Ausdruck kürzer, so dass es bei einer größeren Zahl gesetzter Bits und bei symbolischen Kostanten anstelle der Bitnummern nicht so schnell zu überlangen Zeilen kommt. Soviel zur einer in meinen Augen sinnvollen Klammersetzung bzw. -nichtsetzung. Das Ganze soll primär als Anregung dienen, letztendlich wird jeder einen seinem persönlichen Geschmack angepassten Stil suchen und finden.
Vielen Dank an alle, vor allem an Yalu. Sehr aufschlussreich Deine Antwort, jetzt ist mir die Sache klar. Sehr einleuchtend. Jens
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.