Im Folgenden finden Sie eine Tabelle, die die Rangfolge und Assoziativität aller Operatoren in den Sprachen C und C++ auflistet (wenn die Operatoren auch in Java, Perl, PHP und vielen anderen neueren Sprachen existieren, ist die Rangfolge die gleiche wie die angegebene). Die Operatoren sind von oben nach unten in absteigender Rangfolge aufgelistet. Die absteigende Rangfolge bezieht sich auf die Priorität der Gruppierung von Operatoren und Operanden. Betrachtet man einen Ausdruck, so wird ein Operator, der in einer Zeile aufgeführt ist, vor einem Operator gruppiert, der in einer Zeile weiter unten aufgeführt ist. Operatoren, die sich in der gleichen Zelle befinden (in einer Zelle können mehrere Zeilen mit Operatoren aufgeführt sein), werden mit der gleichen Priorität gruppiert, und zwar in der angegebenen Richtung. Die Rangfolge eines Operators wird durch Überladung nicht beeinflusst.
Die Syntax von Ausdrücken in C und C++ wird durch eine Phrasenstrukturgrammatik festgelegt. Die hier angegebene Tabelle wurde aus dieser Grammatik abgeleitet. Für den ISO C 1999-Standard besagt Abschnitt 6.5.6 Anmerkung 71, dass die von der Spezifikation bereitgestellte C-Grammatik die Rangfolge der C-Operatoren definiert, und besagt auch, dass die sich aus der Grammatik ergebende Operator-Rangfolge eng an die Abschnittsreihenfolge der Spezifikation angelehnt ist:
„Die Syntax spezifiziert die Rangfolge der Operatoren bei der Auswertung eines Ausdrucks, die der Reihenfolge der Hauptunterklauseln dieser Unterklausel entspricht, höchste Rangfolge zuerst.“
Eine Präzedenztabelle ist zwar meist ausreichend, kann aber einige Details nicht auflösen. Insbesondere ist zu beachten, dass der ternäre Operator jeden beliebigen Ausdruck als mittleren Operanden zulässt, obwohl er mit höherer Präzedenz als die Zuweisungs- und Komma-Operatoren aufgeführt ist. So wird a ? b, c : d
als a ? (b, c) : d
interpretiert, und nicht als das bedeutungslose (a ? b), (c : d)
. Der Ausdruck in der Mitte des bedingten Operators (zwischen ?
und :
) wird also so geparst, als wäre er in Klammern gesetzt. Beachten Sie auch, dass das unmittelbare, nicht geklammerte Ergebnis eines C-Cast-Ausdrucks nicht der Operand von sizeof
sein kann. Daher wird sizeof (int) * x
als (sizeof(int)) * x
interpretiert und nicht als sizeof ((int) * x)
.
HinweiseBearbeiten
Die Rangfolge-Tabelle bestimmt die Reihenfolge der Bindung in verketteten Ausdrücken, wenn sie nicht ausdrücklich durch Klammern angegeben ist.
Präzedenz und Bindungen
Viele der Operatoren, die mehrstellige Zeichenfolgen enthalten, erhalten „Namen“, die aus dem Operatornamen der einzelnen Zeichen gebildet werden. Zum Beispiel werden +=
und -=
oft als „Plus-Gleiche(r)“ und „Minus-Gleiche(r)“ bezeichnet, anstelle der etwas umständlicheren „Zuweisung durch Addition“ und „Zuweisung durch Subtraktion“.Die Bindung von Operatoren in C und C++ wird (in den entsprechenden Standards) durch eine faktorisierte Sprachgrammatik spezifiziert, anstatt durch eine Präzedenztabelle. Dies führt zu einigen subtilen Konflikten. Zum Beispiel ist in C die Syntax für einen bedingten Ausdruck:
logical-OR-expression ? expression : conditional-expression
während sie in C++ lautet:
logical-OR-expression ? expression : assignment-expression
Der Ausdruck:
e = a < d ? a++ : a = d
wird also in den beiden Sprachen unterschiedlich geparst. In C ist dieser Ausdruck ein Syntaxfehler, denn die Syntax für einen Zuweisungsausdruck in C ist:
unary-expression '=' assignment-expression
In C++ wird er geparst als:
e = (a < d ? a++ : (a = d))
was ein gültiger Ausdruck ist.
int a = 1, b = 2, weirdVariable = (++a, b), d = 4;
Kritik an der Vorrangigkeit von bitweisen und Gleichheitsoperatoren
Die Vorrangigkeit der bitweisen logischen Operatoren ist kritisiert worden. & und | sind konzeptionell arithmetische Operatoren wie * und +.
Außerdem ergeben Gleichheitsoperationen in C++ (und späteren Versionen von C), mit Ausnahme des Dreiweg-Vergleichsoperators, Werte vom Typ bool, die konzeptionell ein einzelnes Bit (1 oder 0) sind und als solche nicht richtig zu den „bitweisen“ Operationen gehören.
C++-Operator-SynonymeBearbeiten
C++ definiert bestimmte Schlüsselwörter, die als Aliase für eine Reihe von Operatoren dienen:
Schlüsselwort | Operator |
---|---|
und |
&& |
und_eq |
&= |
bitand |
& |
bitor |
| |
compl |
~ |
not |
! |
not_eq |
!= |
oder |
|| |
oder_eq |
|= |
xor |
^ |
xor_eq |
^= |
Diese können genau so verwendet werden wie die Satzzeichen, die sie ersetzen, da es sich nicht um den gleichen Operator unter einem anderen Namen handelt, sondern um einfache Token-Ersetzungen für den Namen (Zeichenkette) des jeweiligen Operators. Das bedeutet, dass die Ausdrücke (ein > 0 und nicht flag)
und (a >&& !flag)
haben identische Bedeutungen. Das bedeutet auch, dass z. B. das Schlüsselwort bitand
nicht nur den bitweisen-und-Operator, sondern auch den address-of-Operator ersetzen kann, und es kann sogar zur Angabe von Referenztypen verwendet werden (z. B. int bitand ref = n
). Die ISO C-Spezifikation sieht diese Schlüsselwörter als Präprozessormakros in der Header-Datei iso646.h
vor. Für die Kompatibilität mit C stellt C++ den Header ciso646
zur Verfügung, dessen Einbindung keine Auswirkungen hat.