C-Programmierung: Operatoren

Aus Wikibooks
Wechseln zu: Navigation, Suche

Grundbegriffe[Bearbeiten]

Bevor wir uns mit den Operatoren näher beschäftigen, wollen wir uns noch einige Grundbegriffe ansehen:

Unäre und binäre Operatoren

Man unterscheidet in der Sprache C unäre, binäre und ternäre Operatoren. Unäre Operatoren besitzen nur einen Operanden, binäre Operatoren besitzen zwei Operanden und ternäre drei. Ein unärer Operator ist beispielsweise der & -Operator, ein binärer Operator der Geteilt-Operator ( / ). Es gibt auch Operatoren, die, je nachdem wo sie stehen, entweder unär oder binär sind. Ein Beispiel hierfür sind Plus ( + ) und Minus ( - ). Sie können als Vorzeichen vorkommen und sind dann unäre Operatoren oder als Rechenzeichen und sind dann binäre Operatoren. Der einzige ternäre Operator in C ist der Bedingungsoperator, der weiter unten behandelt wird.

Sehr häufig kommen im Zusammenhang mit binären Operatoren auch die Begriffe L- und R-Wert vor. Diese Begriffe stammen ursprünglich von Zuweisungen. Der Operand links des Zuweisungsoperators wird als L-Wert (engl. L value) bezeichnet, der Operand rechts als R-Wert (engl. R value). Verallgemeinert gesprochen sind L-Werte Operanden, denen man einen Wert zuweisen kann, R-Werten kann kein Wert zugewiesen werden. Alle beschreibbaren Variablen sind also L-Werte. Konstanten, Literale und konstante Zeichenketten (String Literalen) hingegen sind R-Werte. Je nach Operator dürfen bestimmte Operanden nur L-Werte sein. Beim Zuweisungsoperator muss beispielsweise der erste Operand ein L-Wert sein.

 a = 35;

In der Zuweisung ist der erste Operand die Variable a (ein L-Wert), der zweite Operand das Literal 35 (ein R-Wert). Nicht erlaubt hingegen ist die Zuweisung

 35 = a; /* Fehler */

da einem Literal kein Wert zugewiesen werden darf. Anders ausgedrückt: Ein Literal ist kein L-Wert und darf deshalb beim Zuweisungsoperator nicht als erster Operand verwendet werden. Auch bei anderen Operatoren sind nur L-Werte als Operand erlaubt. Ein Beispiel hierfür ist der Adressoperator. So ist beispielsweise auch der folgende Ausdruck falsch:

 &35; /* Fehler */

Der Compiler wird eine Fehlermeldung ausgeben, in welcher er vermutlich darauf hinweisen wird, dass hinter dem &-Operator ein L-Wert folgen muss.

Inkrement- und Dekrement-Operator[Bearbeiten]

Mit den ++ - und -- -Operatoren kann ein L-Wert um eins erhöht bzw. um eins vermindert werden. Man bezeichnet die Erhöhung um eins auch als Inkrement, die Verminderung um eins als Dekrement. Ein Inkrement einer Variable x entspricht x = x + 1, ein Dekrement einer Variable x entspricht x = x - 1.

Der Operator kann sowohl vor als auch nach dem Operanden stehen. Steht der Operator vor dem Operand, spricht man von einem Präfix, steht er hinter dem Operand bezeichnet man ihn als Postfix. Je nach Kontext unterscheiden sich die beiden Varianten, wie das folgende Beispiel zeigt:

 x = 10;
  ergebnis = ++x;

Die zweite Zeile kann gelesen werden als: "Erhöhe zunächst x um eins, und weise dann den Wert der Variablen zu". Nach der Zuweisung besitzt sowohl die Variable ergebnis wie auch die Variable x den Wert 11.

 x = 10;
  ergebnis = x++;

Die zweite Zeile kann nun gelesen werden als: "Weise der Variablen ergebnis den Wert x zu und erhöhe anschließend x um eins." Nach der Zuweisung hat die Variable ergebnis deshalb den Wert 10, die Variable x den Wert 11.

Der ++- bzw. ---Operator sollte, wann immer es möglich ist, präfix verwendet werden, da schlechte und ältere Compiler den Wert des Ausdruckes sonst (unnötigerweise) zuerst kopieren, dann erhöhen und dann in die Variable zurückschreiben. So wird aus i++ schnell

int j = i;
j = j + 1;
i = j;

wobei der Mehraufwand hier deutlich ersichtlich ist. Auch wenn man später zu C++ wechseln will, sollte man sich von Anfang an den Präfixoperator angewöhnen, da die beiden Anwendungsweisen dort fundamental anders sein können.

Rangfolge und Assoziativität[Bearbeiten]

Wie Sie bereits im ersten Kapitel gesehen haben, besitzen der Mal- und der Geteilt-Operator eine höhere Rangfolge (auch als Priorität bezeichnet) als der Plus- und der Minus-Operator. Diese Regel ist Ihnen sicher noch aus der Schule als "Punkt vor Strich" bekannt.

Was ist mit einem Ausdruck wie beispielsweise:

 c = sizeof(x) + ++a / 3;

In C hat jeder Operator eine Rangfolge, nach der der Compiler einen Ausdruck auswertet. Diese Rangfolge finden Sie in der Referenz dieses Buches.

Der sizeof() - sowie der Präfix-Operator haben die Priorität 14, + die Priorität 12 und / die Priorität 13 [1].

Folglich wird der Ausdruck wie folgt ausgewertet:

 c = (sizeof(x)) + ((++a) / 3);


Neben der Priorität ist bei Operatoren mit der gleichen Priorität auch die Reihenfolge (auch als Assoziativität bezeichnet) der Auswertung von Bedeutung. So muss beispielsweise der Ausdruck

 4 / 2 / 2

von links nach rechts ausgewertet werden:

 (4 / 2) / 2   // ergibt 1

Wird die Reihenfolge dieser Auswertung geändert, so ist das Ergebnis falsch:

 4 / (2 / 2)   // ergibt 4

In diesem Beispiel ist die Auswertungsreihenfolge

 (4 / 2) / 2

, also linksassoziativ.

Nicht alle Ausdrücke werden aber von links nach rechts ausgewertet, wie das folgende Beispiel zeigt:

 a = b = c = d;

Durch Klammerschreibweise verdeutlicht, wird dieser Ausdruck vom Compiler von rechts nach links ausgewertet:

 a = (b = (c = d));

Der Ausdruck ist also rechtsassoziativ.

Dagegen lässt sich auf das folgende Beispiel die Assoziativitätsregel nicht anwenden:

 5 + 4 * 8 + 2

Sicher sieht man bei diesem Beispiel sofort, dass es wegen "Punkt vor Strich" keinen Sinn macht, eine bestimmte Bewertungsreihenfolge festzulegen. Uns interessiert hier allerdings die Begründung die C hierfür liefert: Diese besagt, wie wir bereits wissen, dass die Assoziativitätsregel nur auf Operatoren mit gleicher Priorität anwendbar ist. Der Plusoperator hat allerdings eine geringere Priorität als der Multiplikationsoperator.

Diese Assoziativität von jedem Operator finden Sie in der Referenz dieses Buches.

Durch unsere bisherigen Beispiele könnte der Anschein erweckt werden, dass alle Ausdrücke ein definiertes Ergebnis besitzen. Leider ist dies nicht der Fall.

Fast alle C-Programme besitzen sogenannte Nebenwirkungen (engl. side effect; teilweise auch mit Seiteneffekt übersetzt). Als Nebenwirkungen bezeichnet man die Veränderung des Zustandes des Rechnersystems durch das Programm. Typische Beispiele hierfür sind Ausgabe, Eingabe und die Veränderung von Variablen. Beispielsweise führt i++ zu einer Nebenwirkung - die Variable wird um eins erhöht.

Der C-Standard legt im Programm bestimmte Punkte fest, bis zu denen Nebenwirkungen ausgewertet sein müssen. Solche Punkte werden als Sequenzpunkte (engl. sequence point) bezeichnet. In welcher Reihenfolge die Nebenwirkungen vor dem Sequenzpunkt auftreten und welche Auswirkungen dies hat, ist nicht definiert.

Die folgenden Beispiele sollten dies verdeutlichen:

 i = 3;
 a = i + i++;

Da der zweite Operand der Addition ein Postfix-Inkrement-Operator ist, wird dieser zu 3 ausgewertet. Je nachdem, ob der erste Operand vor oder nach Einsetzen der Nebenwirkung ausgewertet wird (also ob i noch 3 oder schon 4 ist), ergibt die Addition 6 oder 7. Da sich der Sequenzpunkt aber am Ende der Zeile befindet, ist beides möglich und C-konform. Um es nochmals hervorzuheben: Nach dem Sequenzpunkt besitzt i in jedem Fall den Wert 4. Es ist allerdings nicht definiert, wann i inkrementiert wird. Dies kann vor oder nach der Addition geschehen.

Ein weiterer Sequenzpunkt befindet sich vor dem Eintritt in eine Funktion. Hierzu zwei Beispiele:

 a = 5;
 printf("Ausgabe: %d %d",a += 5,a *= 2);

Die Ausgabe kann entweder 10 20, 15 10 oder 15 15 sein, je nachdem ob die Nebenwirkung von a += 5 oder a*= 2 zuerst ausgeführt wird oder ob beide Berechnungen vor der Ausgabe erfolgen.

Zweites Beispiel:

 x = a() + b()  c();

Wie wir oben gesehen haben, ist festgelegt, dass der Ausdruck von links nach rechts ausgewertet wird ( (a() + b()) - c() ), da der Ausdruck linksassoziativ ist. Allerdings steht damit nicht fest, welche der Funktionen als erstes aufgerufen wird. Der Aufruf kann in den Kombinationen a, b, c oder a, c, b oder b, a, c oder b, c, a oder c, a, b oder c, b, a erfolgen. Welche Auswirkungen dies auf die Programmausführung hat, ist undefiniert.

Weitere wichtige Sequenzpunkte sind die Operatoren && , || sowie  ?: und Komma. Auf die Bedeutung dieser Operatoren werden wir noch im nächsten Kapitel näher eingehen.

Es sei nochmals darauf hingewiesen, dass dies nicht wie im Fall eines implementierungsabhängigen oder unspezifizierten Verhalten zu Programmen führt, die nicht portabel sind. Vielmehr sollten Programme erst gar kein undefiniertes Verhalten liefern. Fast alle Compiler geben hierbei keine Warnung aus. Ein undefiniertes Verhalten kann allerdings buchstäblich zu allem führen. So ist es genauso gut möglich, dass der Compiler ein ganz anderes Ergebnis liefert als das Oben beschriebene, oder sogar zu anderen unvorhergesehenen Ereignissen wie beispielsweise dem Absturz des Programms.

Der Shift-Operator[Bearbeiten]

Die Operatoren << und >> dienen dazu, den Inhalt einer Variablen bitweise um 1 nach links bzw. um 1 nach rechts zu verschieben (siehe Abbildung 1).

Beispiel:

1 #include <stdio.h>
2 
3 int main()
4 {
5   unsigned short int a = 350;
6   printf("%u\n", a << 1);
7 
8   return 0;
9 }

Nach dem Kompilieren und Übersetzen wird beim Ausführen des Programms die Zahl 700 ausgegeben. Die Zahl hinter dem Leftshiftoperator << gibt an, um wie viele Bitstellen die Variable verschoben werden soll (in diesem Beispiel wird die Zahl nur ein einziges Mal nach links verschoben).

Abb 1 Linksshift

Vielleicht fragen Sie sich jetzt, für was der Shift–Operator gut sein soll? Schauen Sie sich das Ergebnis nochmals genau an. Fällt Ihnen etwas auf? Richtig! Bei jedem Linksshift findet eine Multiplikation mit 2 statt. Umgekehrt findet beim Rechtsshift eine Division durch 2 statt. (Dies natürlich nur unter der Bedingung, dass die 1 nicht herausgeschoben wird und die Zahl positiv ist. Wenn der zu verschiebende Wert negativ ist, ist das Ergebnis implementierungsabhängig.)

Es stellt sich nun noch die Frage, weshalb man den Shift-Operator benutzen soll, wenn eine Multiplikation mit zwei doch ebenso gut mit dem * -Operator machbar wäre? Die Antwort lautet: Bei den meisten Prozessoren wird die Verschiebung der Bits wesentlich schneller ausgeführt als eine Multiplikation. Deshalb kann es bei laufzeitkritischen Anwendungen vorteilhaft sein, den Shift-Operator anstelle der Multiplikation zu verwenden. Eine weitere praktische Einsatzmöglichkeit des Shift Operators findet sich zudem in der Programmierung von Mikroprozessoren. Durch einen Leftshift können digitale Eingänge einfacher und schneller geschaltet werden. Man erspart sich hierbei mehrere Taktzyklen des Prozessors.

Anmerkung: Heutige Compiler optimieren dies schon selbst. Der Lesbarkeit halber sollte man also besser x * 2 schreiben, wenn eine Multiplikation durchgeführt werden soll. Will man ein Byte als Bitmaske verwenden, d.h. wenn die einzelnen gesetzten Bits interessieren, dann sollte man mit Shift arbeiten, um seine Absicht im Code besser auszudrücken.

Ein wenig Logik …[Bearbeiten]

Kern der Logik sind Aussagen. Solche Aussagen sind beispielsweise:

  • Stuttgart liegt in Baden-Württemberg.
  • Der Himmel ist grün.
  • 6 durch 3 ist 2.
  • Felipe Massa wird in der nächsten Saison Weltmeister.

Aussagen können wahr oder falsch sein. Die erste Aussage ist wahr, die zweite dagegen falsch, die dritte Aussage dagegen ist wiederum wahr. Auch die letzte Aussage ist wahr oder falsch – allerdings wissen wir dies zum jetzigen Zeitpunkt noch nicht. In der Logik werden wahre Aussagen mit einer 1, falsche Aussagen mit einer 0 belegt. Was aber hat dies mit C zu tun? Uns interessieren hier Ausdrücke wie:

  • 5 < 2 (fünf ist kleiner als zwei)
  • 4 == 4 (gleich)
  • 5 >= 2 (wird gelesen als: fünf ist größer oder gleich zwei)
  • x > y (x ist größer als y)

Auch diese Ausdrücke können wahr oder falsch sein. Mit solchen sehr einfachen Ausdrücken kann der Programmfluss gesteuert werden. So kann der Programmierer festlegen, dass bestimmte Anweisungen nur dann ausgeführt werden, wenn beispielsweise x > y ist oder ein Programmabschnitt so lange ausgeführt wird wie a != b ist (in C bedeutet das Zeichen != immer ungleich).

Beispiel: Die Variable x hat den Wert 5 und die Variable y den Wert 7. Dann ist der Ausdruck x < y wahr und liefert eine 1 zurück. Der Ausdruck x > y dagegen ist falsch und liefert deshalb eine 0 zurück.

Für den Vergleich zweier Werte kennt C die folgenden Vergleichsoperatoren:

Operator Bedeutung
< kleiner als
> größer als
<= kleiner oder gleich
>= größer oder gleich
 != ungleich
== gleich

Wichtig: Verwechseln Sie nicht den Zuweisungsoperator = mit dem Vergleichsoperator == . Diese haben vollkommen verschiedene Bedeutungen. Während der erste Operator einer Variablen einen Wert zuweist, vergleicht letzterer zwei Werte miteinander. Da die Verwechslung der beiden Operatoren allerdings ebenfalls einen gültigen Ausdruck liefert, gibt der Compiler weder eine Fehlermeldung noch eine Warnung zurück. Dies macht es schwierig, den Fehler aufzufinden. Aus diesem Grund schreiben viele Programmierer grundsätzlich bei Vergleichen die Variablen auf die rechte Seite, also zum Beispiel 5 == a. Vergißt man mal ein =, wird der Compiler eine Fehlermeldung liefern.

Anders als in der Logik wird in C der boolsche Wert [2] true als Werte ungleich 0 definiert. Dies schließt auch beispielsweise die Zahl 5 ein, die in C ebenfalls als true interpretiert wird. Die Ursache hierfür ist, dass es in der ursprünglichen Sprachdefinition keinen Datentyp zur Darstellung der boolschen Werte true und false gab, so dass andere Datentypen zur Speicherung von boolschen Werten benutzt werden mussten. So schreibt beispielsweise der C-Standard vor, dass die Vergleichsoperatoren einen Wert vom Typ int liefern. Erst mit dem C99-Standard wurde ein neuer Datentyp _Bool eingeführt, der nur die Werte 0 und 1 aufnehmen kann.

… und noch etwas Logik[Bearbeiten]

Wir betrachten die folgende Aussage:

Wenn ich morgen vor sechs Uhr Feierabend habe und das Wetter schön ist, dann gehe ich an den Strand.

Auch dies ist eine Aussage, die wahr oder die falsch sein kann. Im Unterschied zu den Beispielen aus dem vorhergegangen Kapitel, hängt die Aussage "gehe ich an den Strand" von den beiden vorhergehenden ab. Gehen wir die verschiedenen möglichen Fälle durch:

  • Wir stellen am nächsten Tag fest, dass die Aussage, dass wir vor sechs Feierabend haben und dass das Wetter schön ist, falsch ist, dann ist auch die Aussage, dass wir an den Strand gehen, falsch.
  • Wir stellen am nächsten Tag fest, die Aussage, dass wir vor sechs Feierabend haben, ist falsch, und die Aussage, dass das Wetter schön ist, ist wahr. Dennoch bleibt die Aussage, dass wir an den Strand gehen, falsch.
  • Wir stellten nun fest, dass wir vor sechs Uhr Feierabend haben, also die Aussage wahr ist, aber dass die Aussage, dass das Wetter schön ist falsch ist. Auch in diesem Fall ist die Aussage, dass wir an den Strand gehen, falsch.
  • Nun stellen wir fest, dass sowohl die Aussage, dass wir vor sechs Uhr Feierabend haben wie auch die Aussage, dass das Wetter schön ist wahr sind. In diesem Fall ist auch die Aussage, dass das wir an den Strand gehen, wahr.

Dies halten wir nun in einer Tabelle fest:

Eingabe 1 Eingabe 2 Ergebnis
falsch falsch falsch
falsch wahr falsch
wahr falsch falsch
wahr wahr wahr

In der Informatik nennt man dies eine Wahrheitstabelle -- in diesem Fall der UND- bzw. AND-Verknüpfung.

Eine UND-Verknüpfung in C wird durch den &-Operator repräsentiert. Beispiel:

 int a;
 a = 45 & 35

Bitte berücksichtigen Sie, dass bei boolschen Operatoren beide Operanden vom Typ Integer sein müssen.

Eine weitere Verknüpfung ist die Oder-Verknüpfung. Auch diese wollen wir uns an einem Beispiel klar machen:

Wenn wir eine Pizzeria oder ein griechisches Lokal finden, kehren wir ein.

Auch hier können wir wieder alle Fälle durchgehen. Wir erhalten dann die folgende Tabelle (der Leser möge sich anhand des Beispiels selbst davon überzeugen):

Eingabe 1 Eingabe 2 Ergebnis
falsch falsch falsch
falsch wahr wahr
wahr falsch wahr
wahr wahr wahr

Eine ODER-Verknüpfung in C wird durch den | -Operator repräsentiert. Beispiel:

 int a;
 a = 45 | 35

Eine weitere Verknüpfung ist XOR bzw. XODER (exklusives Oder), die auch als Antivalenz bezeichnet wird. Eine Antivalenzbedingung ist genau dann wahr, wenn die Bedingungen antivalent sind, das heißt, wenn A und B unterschiedliche Wahrheitswerte besitzen (siehe dazu untenstehende Wahrheitstabelle).

Man kann sich die XOR-Verknüpfung auch an folgendem Beispiel klar machen:

Entweder heute oder morgen gehe ich einkaufen

Hier lässt sich auf die gleiche Weise wie oben die Wahrheitstabelle herleiten:

Eingabe 1 Eingabe 2 Ergebnis
falsch falsch falsch
falsch wahr wahr
wahr falsch wahr
wahr wahr falsch

Ein XOR–Verknüpfung in C wird durch den ^-Operator repräsentiert. Beispiel:

 int a;
 a = a ^ 35 // in Kurzschreibweise: a ^= 35

Es gibt insgesamt 24=16 mögliche Verknüpfungen. Dies entspricht der Anzahl der möglichen Kombinationen der Spalte c in der Wahrheitstabelle. Ein Beispiel für eine solche Verknüpfung, die C nicht kennt, ist die Äquivalenzverknüpfung. Will man diese Verknüpfung erhalten, so muss man entweder eine Funktion schreiben, oder auf die boolsche Algebra zurückgreifen. Dies würde aber den Rahmen dieses Buches sprengen und soll deshalb hier nicht erläutert werden.

Eine weitere Möglichkeit, die einzelnen Bits zu beeinflussen, ist der Komplement-Operator. Mit ihm wird der Wahrheitswert aller Bits umgedreht:

Eingabe Ergebnis
falsch wahr
wahr falsch

Das Komplement wird in C durch den ~ -Operator repräsentiert. Beispiel:

 int a;
 a = ~45

Wie beim Rechnen mit den Grundrechenarten gibt es auch bei den boolschen Operatoren einen Vorrang. Den höchsten Vorrang hat der Komplement-Operator, gefolgt vom UND-Operator und dem XOR-Operator und schließlich dem ODER-Operator. So entspricht beispielsweise

 a | b & ~c

der geklammerten Fassung

 a | (b & (~c))

Es fragt sich nun, wofür solche Verknüpfungen gut sein sollen. Dies wollen wir an zwei Beispielen zeigen (wobei wir in diesem Beispiel von einem Integer mit 16 Bit ausgehen). Bei den Zahlen 0010 1001 0010 1001 und 0111 0101 1001 1100 wollen wir Bit zwei setzen (Hinweis: Normalerweise wird ganz rechts mit 0 beginnend gezählt). Alle anderen Bits sollen unberührt von der Veränderung bleiben. Wie erreichen wir das? Ganz einfach: Wir verknüpfen die Zahlen jeweils durch eine Oder-Verknüpfung mit 0000 0000 0000 0100. Wie Sie im folgenden sehen, erhalten wird dadurch tatsächlich das richtige Ergebnis:

 0010 1001 0010 1001
 0000 0000 0000 0100
 0010 1001 0010 1101

Prüfen Sie das Ergebnis anhand der Oder-Wahrheitstabelle nach! Tatsächlich bleiben alle anderen Bits unverändert. Und was, wenn das zweite Bit bereits gesetzt ist? Sehen wir es uns an:

 0111 0101 1001 1100
 0000 0000 0000 0100
 0111 0101 1001 1100

Auch hier klappt alles wie erwartet, so dass wir annehmen dürfen, dass dies auch bei jeder anderen Zahl funktioniert.

Wir stellen uns nun die Frage, ob Bit fünf gesetzt ist oder nicht. Für uns ist dies sehr einfach, da wir nur ablesen müssen. Die Rechnerhardware hat diese Fähigkeit aber leider nicht. Wir müssen deshalb auch in diesem Fall zu einer Verknüpfung greifen: Wenn wir eine beliebige Zahl durch eine Und–Verknüpfung mit 0000 0000 0010 0000 verknüpfen, so muss das Ergebnis, wenn Bit fünf gesetzt ist, einen Wert ungleich null ergeben, andernfalls muss das Ergebnis gleich null sein.

Wir nehmen nochmals die Zahlen 0010 1001 0010 1001 und 0111 0101 1001 1100 für unser Beispiel:

 0010 1001 0010 1001
 0000 0000 0010 0000
 0000 0000 0010 0000

Da das Ergebnis ungleich null ist, können wir darauf schließen, dass das Bit gesetzt ist. Sehen wir uns nun das zweite Beispiel an, in dem das fünfte Bit nicht gesetzt ist:

 0111 0101 1001 1100
 0000 0000 0010 0000
 0000 0000 0000 0000

Das Ergebnis ist nun gleich null, daher wissen wir, dass das fünfte Bit nicht gesetzt sein kann. Über eine Abfrage, wie wir sie im nächsten Kapitel kennenlernen werden, könnten wir das Ergebnis für unseren Programmablauf benutzen.

Bedingungsoperator[Bearbeiten]

Der Bedingungsoperator liefert abhängig von einer Bedingung einen von zwei möglichen Ergebniswerten. Er hat drei Operanden: Die Bedingung, den Wert für den Fall, dass die Bedingung zutrifft und den Wert für den Fall dass sie nicht zutrifft. Die Syntax ist

     bedingung ? wert_wenn_wahr : wert_wenn_falsch

Für eine einfache if-Anweisung wie die folgende:

 /* Falls a größer als b ist, wird a zurückgegeben, ansonsten b. */
 if (a > b)
    return a;
  else
    return b;

kann daher kürzer geschrieben werden

 return (a > b) ? a : b;
 /* Falls a größer als b ist, wird a zurückgegeben, ansonsten b. */

Der Bedingungsoperator ist nicht, wie oft angenommen, eine verkürzte Schreibweise für if-else. Die wichtigsten Unterschiede sind:

  • Der Bedingungsoperator hat im Gegensatz zu if-else einen Ergebniswert und kann daher z.B. in Formeln und Funktionsaufrufen verwendet werden
  • Bei if-Anweisungen kann der else-Teil entfallen, der Bedingungsoperator verlangt stets eine Angabe von beiden Ergebniswerten

Selbstverständlich können Ausdrücke mit diesem Operator beliebig geschachtelt werden. Das Maximum von drei Zahlen erhalten wir beispielsweise so:

 return a > b ? (a > c ? a : c) : (b > c ? b : c);

An diesem Beispiel sehen wir auch sofort einen Nachteil des Bedingungsoperators: Es ist sehr unübersichtlich, verschachtelten Code mit ihm zu schreiben.



  1. Die Rangfolge der Operatoren ist im Standard nicht in Form einer Tabelle festgelegt, sondern ergibt sich aus der Grammatik der Sprache C. Deshalb können sich die Werte für die Rangfolge in anderen Büchern unterscheiden, wenn eine andere Zählweise verwendet wurde, andere Bücher verzichten wiederum vollständig auf die Durchnummerierung der Rangfolge.
  2. Der Begriff boolsche Werte ist nach dem englischen Mathematiker George Boole benannt, der sich mit algebraischen Strukturen beschäftigte, die nur die Zustände 0 und 1 bzw. false und true kennt.