Algorithmen & Programmierung Ausdrücke & Operatoren (1)
Ausdrücke Was ist ein Ausdruck? Literal Variable Funktionsaufruf Ausdruck, der durch Anwendung eines einstelligen (unären) Operators auf einen Ausdruck entsteht Ausdruck, der durch Anwendung eines zweistelligen (binären) Operators auf zwei Ausdrücke entsteht Ausdruck, der durch Anwendung eines dreistelligen (ternären) Operators auf drei Ausdrücke entsteht Gemeinsame Eigenschaft Jede Komponente eines Ausdrucks (Teilausdruck) besitzt einen Wert. 271
Literale Bedeutung Literale bezeichnen direkte Werte eines Basistyps in C. Wir unterscheiden logische, numerische und Zeichenliterale. Für Literale gelten syntaktische Regeln, damit der Compiler sie identifizieren kann. Datentyp bool int float double Zeichenkette Literale (Beispiele) true false -15263 56-1.0 4.56e-12 "Guten Morgen" 272
Operatoren Operatoren in C () [] ->.! ~ ++ -- + - * & sizeof / % << >> < <= > >= ==!= ^ &&?: = += -= *= /= %= &= ^= = <<= >>=, Stelligkeit von Operatoren einstellige (unäre) Operatoren haben genau einen Operanden, z.b. Vorzeichenoperator - zweistellige (binäre) Operatoren haben genau zwei Operanden, z.b. Additionsoperator + dreistellige (ternäre) Operatoren haben genau drei Operanden, z.b. Bedingungsoperator?: Operand Die Operanden eines Operators sind Ausdrücke. Rückgabewert Alle Operatoren haben einen Rückgabewert. 273
Interpretation von Ausdrücken Ausdrücke können je nach Kontext verschieden interpretiert werden: nach ihrem tatsächlichen (meist arithmetischen) Wert nach einem Wahrheitswert (Wert Null entspricht false, jeder andere Wert entspricht true) Da jeder Ausdruck in C einen Wert zurückliefert und Werte grundsätzlich als Wahrheitswerte interpretierbar sind, können wir für Selektion und Iteration ganz allgemein schreiben: Selektion if ( Ausdruck ) // Wenn Wert von Ausdruck ungleich 0 bzw. true Anweisung1 // wird Anweisung1 ausgeführt else // sonst Anweisung2 // wird Anweisung2 ausgeführt Iteration while ( Ausdruck ) // Solange Wert von Ausdruck ungleich 0 bzw. true Anweisung // wird Anweisung ausgeführt 274
Auswertung von Ausdrücken
Auswertung von Ausdrücken Ausdrücke müssen ausgewertet werden. Dabei wird aus den Werten der einzelnen Komponenten des Ausdrucks ein Gesamtwert ermittelt, der sich aus der Semantik der verwendeten Operatoren ergibt. Jeder Ausdruck besitzt einen Wert. Die Reihenfolge der Auswertung von Ausdrücken ist in C genau festgelegt: Priorität Jeder Operator besitzt eine bestimmte Prioriät Die Operatoren werden in der Reihenfolge ihrer Priorität ausgeführt, wobei die Ausführung mit den Operatoren der höchsten Priorität beginnt. Ausnahme Klammerung innerhalb von Ausdrücken setzt die Festlegung der Auswertungsreihenfolge nach Priorität außer Kraft. 276
Priorität der Operatoren Operator Symbol Priorität Operator Symbol Priorität Elementselektion. 15 unäres Plus + 14 Zeigerselektion -> 15 Adresse & 14 Indizierung [] 15 Dereferenzierung * 14 Funktionsaufruf () 15 Typumwandlung () 14 Postinkrement ++ 15 Multiplikation * 13 Postdekrement -- 15 Division / 13 Objekt-/Typgröße sizeof 14 Modulo % 13 Präinkrement ++ 14 Addition + 12 Prädekrement -- 14 Subtraktion - 12 Komplement ~ 14 Linksschieben << 11 Negation! 14 Rechtsschieben >> 11 unäres Minus - 14 277
Priorität der Operatoren Operator Symbol Priorität Operator Symbol Priorität Kleiner < 10 Multiplikation und Zuweisung *= 3 Kleiner gleich <= 10 Division und Zuweisung /= 3 Größer > 10 Modulo und Zuweisung %= 3 Größer gleich >= 10 Addition und Zuweisung += 3 Gleichheit == 9 Subtraktion und Zuweisung -= 3 Ungleichheit!= 9 Linksschieben und Zuweisung <<= 3 Bitweises Und & 8 Rechtsschieben und Zuweisung >>= 3 Bitweises XOR ^ 7 Bitweises Und und Zuweisung &= 3 Bitweises Oder 6 Bitweises Oder und Zuweisung = 3 Logisches Und && 5 Bitweises XOR und Zuweisung ^= 3 Logisches Oder 4 Bedingungsoperator?: 2 Zuweisung = 3 Komma, 1 278
Auswertung von Ausdrücken Die Reihenfolge der Auswertung von Ausdrücken ist in C genau festgelegt: Assoziativität Besitzen zwei mögliche nächste Operatoren dieselbe Priorität, dann entscheidet die Assoziativität über die Reihenfolge der Auswertung. Binäre Operatoren Mit Ausnahme des Zuweisungsoperators sind alle binären Operatoren linksassoziativ (links bindend), d.h. dass Operatoren mit gleicher Priorität in der Reihenfolge ihres Auftretens ausgewertet werden. Weitere Operatoren Unäre und ternäre Operatoren sind rechtsassoziativ Ausnahme Eine Klammerung von Ausdrücken setzt die Auswertungsreihenfolge bzgl. Assoziativität außer Kraft. 279
Auswertung von Ausdrücken Achtung Die Berechnungsreihenfolge von Operanden wird durch die Priorität und Assoziativität geregelt. Diese Regelung bezieht sich jedoch nur auf die Frage, in welcher Reihenfolge die Werte der Operanden in die Berechnung einfließen. Falls die Operanden selbst wieder zusammengesetzte Ausdrücke sind, wird keine Aussage darüber getroffen, welcher dieser Teilausdrücke zuerst ausgewertet wird. Diese Entscheidung trifft (bis auf drei Ausnahmen) ausschließlich der Compiler. Konsequenz bei Verwendung von Funktionen in Ausdrücken Spielt die Aufrufreihenfolge von zwei oder mehr Funktionen eine Rolle, dann darf in einem Ausdruck maximal ein Funktionsaufruf durchgeführt werden. 280
Auswertung von Ausdrücken Motivation Bei den logischen Verknüpfungsoperatoren && und kann oft das Ergebnis des Gesamtausdrucks bestimmt werden, ohne den Ausdruck komplett berechnen zu müssen. Kurzschlussoperatoren Bei den logischen Verknüpfungsoperatoren && und ist im Gegensatz zu den meisten anderen Operatoren die Auswertungsreihenfolge von Teilausdrücken festgelegt. Die verknüpften Teilausdrücke werden stets von links nach rechts ausgewertet. Dabei ist jedoch zu beachten, dass bei gemeinsamen Auftreten der beiden Operatoren && eine höhere Priorität als hat. Die Auswertung endet, wenn das Ergebnis feststeht (und es sinnbildlich zum Kurzschluss kommt). Achtung Insbesondere bei der Verwendung von Funktionsaufrufen in logisch verknüpften Ausdrücken ist Vorsicht geboten. 281
Ausdrucksanweisungen
Ausdrucksanweisungen Regel In C kann jeder Ausdruck zu einer Anweisung werden. Dies geschieht einfach durch Anhängen eines Semikolons an einen beliebigen Ausdruck. Ausdruck versus Anweisung Ausdrücke haben immer einen Wert und können damit Teil eines größeren Ausdrucks sein. Anweisungen können dies aufgrund des fehlenden (bzw. nicht berücksichtigten) Wertes nicht. Ausdruck versus Funktion Ein Ausdruck kann als Funktion seiner Variablen betrachtet werden. Der Wert eines Ausdrucks korrespondiert damit zum Funktionswert einer Funktion. Wie ein Funktionswert besitzt auch der Wert eines Ausdrucks einen Typ, der jedoch meist nicht im Vorhinein feststeht, sondern sich bei Typverschiedenheit meist aus den Regeln der impliziten Typumwandlung ergibt. 283
Ausdrucksanweisungen Problem Ausdrucksanweisungen vergessen ihren berechneten Wert. Nebeneffekte Es gibt einige Operatoren, die während der Auswertung eines Ausdrucks auch die Werte von Variablen verändern können. Diese Nebenwirkungen werden als Nebeneffekte (manchmal auch fälschlicherweise als Seiteneffekte) bezeichnet. Verwendung von Ausdrucksanweisungen Ausdrucksanweisungen sind nur dann sinnvoll, wenn der zugrundeliegende Ausdruck Nebeneffekte bewirkt. Beispiel Wir haben bereits eine Ausdrucksanweisung mit Nebeneffekten verwendet: Die Zuweisungsoperation 284
Die Zuweisung Zuweisung als Ausdruck Ein Variablenzuweisung mit dem Operator = stellt einen gültigen Ausdruck in C dar. Nebeneffekt Die Nebenwirkung der Zuweisungsoperation stellt die Wertänderung einer Variablen, d.h. eines Speicherobjektes dar. Rückgabewert Der zugewiesene Wert ist gleichzeitig der Rückgabewert des Ausdrucks Zuweisung. Nützliche Konsequenz Mehrfachzuweisungen 285
Die Zuweisung Zuweisung als Ausdruck Ein Variablenzuweisung mit dem Operator = stellt einen gültigen Ausdruck in C dar. Achtung Der Rückgabewert des Zuweisungsoperators sollte niemals in weiteren Berechnungen genutzt werden. Gefährliche Fehlerquelle Da Zuweisungen an jeder Stelle möglich sind, an der Ausdrücke stehen können, besteht auch die syntaktische Möglichkeit, Zuweisungen als Selektions- oder Iterationskriterien zu verwenden. Hierbei kommt es zur (meist unabsichtlichen) Verwechslung der Vergleichsoperators == mit dem Zuweisungsoperator =. Dies ist eine häufige und gefährliche Fehlerquelle in C-Programmen! 286
Die Zuweisung Besonderheit Aufgrund des bei der Zuweisung auftretenden Nebeneffektes der Wertveränderung eines Objekts darf die linke Seite des Zuweisungsoperators nicht irgendein beliebiger Ausdruck sein, sondern muss genau ein Objekt darstellen, das Werte speichern kann. Lvalue Ein Ausdruck stellt ein Lvalue (left value) dar, wenn er sich auf ein Speicherobjekt bezieht. Lvalues können links und rechts des Zuweisungsoperators stehen. Rvalue Ein Ausdruck, der kein Lvalue darstellt wird als Rvalue (right value) bezeichnet Er bezieht sich nicht auf ein Speicherobjekt und deshalb kann ihm kein Wert zugewiesen werden Rvalues dürfen ausschließlich rechts des Zuweisungsoperators stehen 287
Ende der Vorlesung