Ausdrücke sind Folgen von Operanden (Elementarausdrücke) und
Operatoren. Die Bearbeitung eines Ausdrucks liefert in C jeweils einen
Typ und einen Wert.
In C stehen dem Programmierer insgesamt 46 Operatoren zur Verfügung, die in drei Klassen unterteilt werden können:
Da es bei der Bearbeitung von Ausdrücken mit mehreren verschiedenen Operatoren entscheidend ist, in welcher Reihenfolge dies geschieht, wurden den Operatoren verschiedene Prioritäten zugeordnet. Insgesamt gibt es 15 Stufen, wobei die 1. die niedrigste und die 15. die höchste Stufe darstellt. Bei den Operatoren mit der gleichen Priorität wird die Abarbeitungsreihenfolge durch die Analyserichtung bestimmt.
Die Operatoren können in funktionale Gruppen eingeteilt werden,
auf die in den nächsten Abschnitten einzeln eingegangen wird.
( ) Klammer-Operator
Mit Hilfe der runden Klammern kann auf die Auswertung von Ausdrücken
bewusst Einfluss genommen werden.
Beispiel: ergebnis = x * y - z;
ergebnis = x * (y - z);
In der ersten Zeile des Beispiels wird zuerst die Multiplikation und
dann die Subtraktion ausgeführt. Durch die Klammerung wird in der
zweiten Zeile zuerst die Subtraktion und dann die Multiplikation ausgeführt.
[ ] Array - Operator
Mit Hilfe der eckigen Klammern werden Feldelemente beschrieben. Die
Anwendung dieser Klammern erfolgt bei der Deklaration von Feldern und beim
Zugriff auf Feldelemente.
Beispiel: int variable, vektor[10], matrix[7][7];
...
variable = vektor[4];
...
variable = matrix[6][2];
. Struktur-Operator
Der Punkt-Operator wird zur Steuerung des Zugriffs auf Strukturkomponenten
einer vereinbarten Struktur benutzt.
Beispiel: person.vorname;
person.beruf;
-> Zeiger-Operator auf Strukturen
Der Zugriff auf Strukturen über Zeiger erfolgt mit dem Zeiger-Operator,
auch Strukturverweiskomponente genannt.
Beispiel: person_zeiger->vorname
person_zeiger->beruf
! Logische Negation
Die logische Negation kehrt den Wahrheitsgehalt eines Wertes um, d.
h. aus dem Wert Null (falsch) wird eine 1 und aus jedem Wert ungleich Null
(wahr) entsteht Null..
Beispiel: !3 ergibt 0 (falsch)
!0 ergibt 1 (wahr)
~ Bitweises Komplement
Das bitweise Komplement erzeugt das Einerkomplement eines gegebenen
Wertes und wirkt auf die gesamte Länge.
Im Beispiel soll das Einerkomplement aus z = ~7 gebildet werden. In einer Wortlänge von 2 Byte, lässt sich der Wert wie folgt darstellen :
7 binär: 0000 0000 0000 0111 hexadezimal: 0x0007
Nach bitweisem Komplement entsteht:
-7 binär: 1111 1111 1111 1000
hexadezimal: 0xFFF8
++ Inkrement
Das Inkrement dient zum Erhöhen (Inkrementieren) von Variablen
und dient im Wesentlichen zur kürzeren Schreibweise des Ausdrucks
x = x + 1. Der neue Wert von x ergibt sich aus dem alten Wert von x plus
1. Auf Konstanten und Ausdrücken kann dieser Operator nicht angewandt
werden.
Beispiel: x = 5;
x++; entspricht x = x + 1;
Im Beispiel hat die Variable nach der Inkrementierung den Wert 6.
-- Dekrement
Das Dekrement dient zum Vermindern (Dekrementieren) von Variablen und
dient zur Schreibweise des Ausdrucks x = x - 1. Der neue Wert von
x ergibt sich aus dem alten Wert von x minus 1. Auf Konstante
und Ausdrücke kann dieser Operator nicht angewandt werden.
Beispiel: x = 5;
x--; entspricht x = x - 1;
Im Beispiel hat die Variable nach der Dekrementierung den Wert 4.
- unäres Minus (Vorzeichen)
Das unäre Minuszeichen liefert den negativen Wert des Operanden.
Beispiel: wert = -6;
(typ) explizite Typkonvertierung (Cast-Operator)
Mit Hilfe des Cast-Operators wird der Typ eines Operanden verändert.
So veranlasst die Schreibung von (typ) A, dass der Ausdruck A
im Typ typ dargestellt wird.
Beispiel: (int) sqrt(13.4)
Das Ergebnis der Quadratwurzeloperation wird in eine Ganzzahl umgewandelt.
Der entstehende Wert beträgt 3.
* Inhalts-Operator
Bei der Arbeit mit Zeigern wird auf Variablen über ihren Speicherplatz
zugegriffen. Der Inhalts-Operator, auch Zeiger-Operator genannt, auf eine
Variable angewendet, bewirkt, dass der Wert der Variablen als Adresse interpretiert
wird und das Objekt, das unter dieser Adresse abgespeichert ist, bereitgestellt
ist. Im Beispiel erhält mit der Anweisung wert = * zeiger die Ganzzahlvariable
wert den Wert der Variablen des Speicherplatzes zugewiesen,
auf den der Zeiger zeiger hinweist.
Beispiel: int wert, * zeiger;
...
zeiger = ...
...
wert = *zeiger;
& Adress-Operator
Im Gegensatz zum Inhalts-Operator, liefert der Adress-Operator die Adresse
eines Objektes. Er tritt zum Beispiel dann auf, wenn es darum geht einen
Zeiger zu initialisieren.
Beispiel: int wert1 = 5, wert2, *zeiger;
...
zeiger = &wert1;
wert2 = *zeiger;
Damit erhält die Variable wert2 den Wert 5.
sizeof sizeof-Operator
Mit dem sizeof-Operator kann die Anzahl der Bytes festgestellt werden, die für einen Typ festgelegt oder für ein Objekt zum Speichern gebraucht werden.
Die Anwendung des sizeof-Operators ist für Typnamen und Ausdrücke
(Namen von einfachen Variablen, Feldern oder Feldkomponenten) möglich.
Beispiel: int laenge, variable, feld[10];
laenge = sizeof (variable);
laenge = sizeof (feld);
laenge = sizeof (feld[3]);
laenge = sizeof (int);
* Multiplikation
Beispiel: x = 3.5 * y;
/ Division
Sind beide Operanden ganzzahlig, wird auch eine ganzzahlige Division
ausgeführt.
Beispiel: x = 3 / 4;
Die Variable x erhält in diesem Fall den Wert 0.
% Modulo-Division
Die Modulo-Division x%y ermittelt den Divisionsrest von x durch y, wobei
x und y ganze Zahlen sein müssen.
Beispiel: x = 3 % 4
x = 10 % 4
x = -2 % 4
Im ersten Fall des Beispiels erhält x der Wert 3,
im zweiten 2 und im letzten -2.
+ Addition
Beispiel: x = y + z;
- Subtraktion
Beispiel: x = 3 - 5 -y;
<< bitweises Schieben nach links
>> bitweises Schieben nach rechts
Die Schiebe-Operatoren, auch shift-Operatoren genannt, verschieben das
Bitmuster des ersten Operanden um die im zweiten Operanden angegebenen
Stellen. Der Operator bestimmt dabei die Richtung, in der verschoben wird.
Die Bits, die über die Grenze hinausgeschoben werden, entfallen, während
die freiwerdenden Stellen mit Nullen aufgefüllt werden.
Beispiel: int a, b, c;
a = 18;
b = 4;
c = a << b;
d = a >> b;
Im Beispiel erhält c den Wert 288 und d den Wert 1.
Ein Schieben um n Bit nach links entspricht einer Multiplikation mit
dem Faktor 2^n, ein Schieben nach rechts um n Bit entspricht der Division
durch den Faktor 2^n.
< kleiner
> größer
<= kleiner gleich
>= größer gleich
= = gleich
!= ungleich
Die Vergleichsoperatoren dienen dazu, zwei Operatoren gleichen Typs miteinander zu vergleichen. Ist der durch den Operator vorgegebene Vergleich richtig, so wird als Ergebnis eine 1, im anderen Fall eine 0 zurückgegeben. Das Ergebnis ist vom Typ Integer.
Es gilt zu beachten, dass ein Vergleich auf Gleichheit mit einem doppelten
Gleichheitszeichen auszuführen ist, da ein einfaches Gleichheitszeichen
eine Zuweisung darstellt
& bitweises UND (AND)
Der bitweise Und-Operator verknüpft jedes Bitpaar der ganzzahligen
Operanden durch ein Und. Der Und-Operator liefert dann eine 1, wenn beide
Bits der Operanden 1 sind, sonst liefert er den Wert 0.
Beispiel: a = 0X55; /* 0101 0101 */
b = 0X4F; /* 0100 1111 */
c = a & b; /* 0100 0101 */
^ exklusives ODER (XOR)
Der bitweise XOR-Operator kann nur auf ganzzahlige Operanden angewandt
werden. Der XOR-Operator liefert genau dann eine 1, wenn genau eines der
beiden Bits der Operanden 1 ist.
Beispiel: a = 0X55; /* 0101 0101 */
b = 0X4F; /* 0100 1111 */
c = a ^ b; /* 0001 1010 */
| bitweises ODER (OR)
Der bitweise Oder-Operator verknüpft jedes Bitpaar der ganzzahligen
Opernanden über ein inklusives Oder. Der Oder-Operator liefert genau
dann eine 1, wenn mindestens ein Bit der beiden Operanden 1 ist.
Beispiel: a = 0X55; /* 0101 0101 */
b = 0X4F; /* 0100 1111 */
c = a | b; /* 0101 1011 */
&& logisches UND zweier Wahrheitswerte
Der logische Und-Operator kann nur auf ganzzahlige Operanden angewandt
werden. Er liefert den Wert 1, wenn beide Operanden ungleich 0 sind.
Beispiel: a = 24;
b = 189;
c = 0;
d = 0;
e = a && b; /* e = 1 */
e = a && c; /* e = 0 */
e = c && d; /* e = 0 */
|| logisches ODER
Der logische Oder-Operator kann nur auf ganzzahlige Operanden angewandt
werden. Er liefert den Wert 1, wenn mindestens einer der beiden Operanden
ungleich 0 ist.
Beispiel: a = 24;
b = 189;
c = 0;
d = 0;
e = a || b; /* e = 1 */
e = a || c; /* e = 1 */
e = c || d; /* e = 0 */
? Operator für bedingte Ausdrücke
Dieser Operator ermöglicht es, eine einfache if-Aussage
zu formulieren. Die Schreibweise sieht wie folgt aus:
ausdruck1 ? ausdruck2 : ausdruck3;
Ist der Wert des ersten Ausdrucks wahr, also ausdruck1 ungleich
Null, liefert der Operator als Wert ausdruck2, andernfalls ausdruck3.
Beispiel: return(((a + b) > c) ? d : e );
Diese Anweisung ist gleichbedeutend mit der folgenden if-else-Konstruktion:
Beispiel: if ((a+b) > c)
return(d);
else
return(e);
= einfache Zuweisung
Der Zuweisungsoperator dient zur Formulierung der Ergibtanweisung.
Beispiel: int a, b;
...
a = b + 4;
Darüber hinaus gibt es noch eine Reihe von zusammengesetzten Zuweisungsoperatoren, die sich aus der Kombination der vorangegangenen Operatoren und dem Zuweisungsoperator, dem Gleichheitszeichen, ergeben. Die Schreibweise
variable_links = variable_links <operator> (ausdruck)
kann so durch die Schreibweise
variable_links <operator> = (ausdruck)
ersetzt werden. bei der Abarbeitung wird dabei zuerst der Ausdruck auf
der rechten Seite berechnet und anschließend mit der variable_links
verknüpft.
Beispiele: a += 5; /* a = a + 5 */
a -= 5; /* a = a - 5 */
a *= 5; /* a = a * 5 */
a /= 5; /* a = a / 5 */
a %= 5; /* a = a % 5 */
a >>= 5; /* a = a >> 5 */
a <<= 5; /* a = a << 5 */
a &= 5; /* a = a & 5 */
a |= 5; /* a = a | 5 */
a ^= 5; /* a = a ^ 5 */
Das Beispiel zeigt mögliche Kombinationen, die eine verkürzte Schreibweise darstellen. Im Kommentar steht die ausgeschriebene Variante.
3.10 Postfix- und
Präfix-Schreibweisen
Muss laufend eine Zählvariable beispielsweise addiert werden, so kann statt
zaehl = zaehl + 1 auch
zaehl += 1 oder, neu und verkürzt
zaehl ++
geschrieben werden. Entsprechendes gilt für die Subtraktion.
Die Benutzung dieser Präfix- und Postfix-Schreibweisen hat innerhalb von Ausdrücken eine besondere Bedeutung.
Wird die Postfix-Schreibweise verwendet, der Operator also nachgestellt, so bewirkt dies, dass zuerst eine Zuweisung des Ausdrucks auf der rechten Seite an die Variable auf der linken Seite erfolgt. Erst danach wird die Variable auf der rechten Seite hochgezählt.
variable_links = variable_rechts++; <==> variable_links = variable_rechts;
variable_rechts + 1;
Im Gegensatz dazu steht die Präfix-Schreibweise, bei der der Operator dem Operanden vorangestellt wird. Hier wird zuerst die Variable auf der rechten Seite hochgezählt und erst dann der Variablen auf der linken Seite zugewiesen.
variable_links = ++variable_rechts; <==> variable_rechts + 1; variable_links
= variable_rechts;
, Komma-Operator
Der Sequenz-Operator, oder auch Kommaoperator, legt eine Links-Rechts-Abarbeitungsreihenfolge
von gleichberechtigten Ausdrücken fest. Er erlaubt es auch zwei Ausdrücke
zu syntaktisch einem zusammenzufassen.
Beispiel: a = ( b = 1, b += 2); /* a = 3 */
/* b = 3 */
Das Beispiel zeigt die Wirkungsweise des Komma-Operators. In den Kommentaren
stehen die Werte , die den Variablen a und b zugewiesen werden.