Andere Operatoren
Eine Sammlung von Operatoren, die in keine der anderen Hauptkategorien passen.
| Dieser Abschnitt ist unvollständig Grund: Erwägen Sie ein allgemeineres Inhaltsverzeichnis für diese und andere Tabellen, die mehrere Themen abdecken |
| Operator | Operatorname | Beispiel | Beschreibung |
|---|---|---|---|
| (...) | Funktionsaufruf | f(...) | ruft die Funktion f() mit null oder mehr Argumenten auf |
| , | Komma-Operator | a, b | wertet den Ausdruck a aus, verwirft dessen Rückgabewert und führt alle Seiteneffekte aus, wertet dann den Ausdruck b aus und gibt Typ und Ergebnis dieser Auswertung zurück |
| (Typ) | Typumwandlung | (Typ)a | wandelt den Typ von a in Typ um |
| ? : | bedingter Operator | a ? b : c | wenn a logisch wahr ist (nicht zu null ausgewertet wird), dann wird der Ausdruck b ausgewertet, andernfalls wird der Ausdruck c ausgewertet |
| sizeof | sizeof-Operator | sizeof a | die Größe von a in Bytes |
| _Alignof (seit C11) |
_Alignof-Operator | _Alignof(Typ) | die Ausrichtung, die für Typ erforderlich ist |
| typeof | typeof-Operatoren | typeof(a) | der Typ von a |
Inhalt |
[bearbeiten] Funktionsaufruf
Der Ausdruck für den Funktionsaufruf hat die Form
Ausdruck ( Argumentliste (optional) ) |
|||||||||
wobei
| expression | - | jeder Ausdruck vom Typ Zeiger auf Funktion (nach lvalue-Konvertierungen) |
| Argumentliste | - | kommagetrennte Liste von Ausdrücken (die keine Komma-Operatoren sein dürfen) von beliebigen vollständigen Objekttypen. Kann weggelassen werden, wenn Funktionen ohne Argumente aufgerufen werden. |
Das Verhalten des Funktionsaufrufausdrucks hängt davon ab, ob der Prototyp der aufgerufenen Funktion zum Zeitpunkt des Aufrufs im Geltungsbereich liegt.
[bearbeiten] Aufruf einer Funktion mit Prototyp
|
Zusätzlich muss für jeden Parameter vom Array-Typ, der das Schlüsselwort
static zwischen [ und ] verwendet, der Argumentausdruck auf einen Zeiger auf das Element eines Arrays mit mindestens so vielen Elementen verweisen, wie im Größenparameter des Parameters angegeben. |
(seit C99) |
- Wenn ein nachgestellter Ellipsenparameter vorhanden ist, werden Standardargument-Promotions auf die verbleibenden Argumente angewendet, die für va_list verfügbar gemacht werden.
void f(char* p, int x) {} int main(void) { f("abc", 3.14); // array to pointer and float to int conversions }
Aufruf einer Funktion ohne Prototyp1) Die Argumente werden in nicht spezifizierter Reihenfolge und ohne Sequenzierung ausgewertet.
2) Auf jedes Argument werden Standardargument-Promotions angewendet.
3) Zuweisung erfolgt, um den Wert jedes Arguments auf den entsprechenden Funktionsparameter zu kopieren, wobei alle Typqualifizierer auf dem Parametertyp und seinen möglicherweise rekursiven Elementen oder Mitgliedern ignoriert werden.
4) Die Funktion wird ausgeführt und der zurückgegebene Wert wird zum Wert des Funktionsaufrufausdrucks (wenn die Funktion void zurückgibt, ist der Funktionsaufrufausdruck ein void-Ausdruck)
void f(); // no prototype int main(void) { f(1, 1.0f); // UB unless f is defined to take an int and a double } void f(int a, double c) {} Das Verhalten eines Funktionsaufrufs einer Funktion ohne Prototyp ist undefiniert, wenn
|
(bis C23) |
[bearbeiten] Hinweise
Die Auswertungen von Ausdruck, der die aufzurufende Funktion bezeichnet, und aller Argumente sind unsequenziert zueinander (aber es gibt einen Sequenzpunkt, bevor der Körper der Funktion ausgeführt wird)
(*pf[f1()]) (f2(), f3() + f4()); // f1, f2, f3, f4 may be called in any order
Obwohl Funktionsaufrufe nur für Zeiger auf Funktionen definiert sind, funktionieren sie aufgrund der impliziten Konvertierung von Funktion zu Zeiger auch mit Funktionsbezeichnern.
int f(void) { return 1; } int (*pf)(void) = f; int main(void) { f(); // convert f to pointer, then call (&f)(); // create a pointer to function, then call pf(); // call the function (*pf)(); // obtain the function designator, convert to pointer, then calls (****f)(); // convert to pointer, obtain the function, repeat 4x, then call (****pf)(); // also OK }
Funktionen, die ungenutzte Argumente ignorieren, wie z. B. printf, müssen mit einem Prototyp im Geltungsbereich aufgerufen werden (der Prototyp solcher Funktionen verwendet zwangsläufig den nachgestellten Ellipsenparameter), um undefiniertes Verhalten zu vermeiden.
Die aktuelle Standardformulierung der Semantik der Vorbereitung von Funktionsparametern ist fehlerhaft, da sie besagt, dass Parameter beim Aufruf aus Argumenten zugewiesen werden, was const-qualifizierte Parameter- oder Mitgliedstypen fälschlicherweise ablehnt und unangemessen die Semantik von volatile anwendet, was auf vielen Plattformen für Funktionsparameter nicht implementierbar ist. Ein Post-C11-Fehlerbericht DR427 schlug eine Änderung der Semantik von Zuweisung zu Initialisierung vor, wurde aber als kein Fehler geschlossen.
|
Ein Funktionsaufrufausdruck, bei dem Ausdruck ausschließlich aus einem Bezeichner besteht und dieser Bezeichner nicht deklariert ist, verhält sich so, als wäre der Bezeichner deklariert als extern int identifier(); // returns int and has no prototype Somit ist das folgende vollständige Programm gültig C89 main() { int n = atoi("123"); // implicitly declares atoi as int atoi() } |
(bis C99) |
[bearbeiten] Komma-Operator
Der Ausdruck des Komma-Operators hat die Form
lhs , rhs |
|||||||||
wobei
| lhs | - | beliebiger Ausdruck |
| rhs | - | beliebiger Ausdruck außer einem weiteren Komma-Operator (mit anderen Worten, die Assoziativität des Komma-Operators ist von links nach rechts) |
Zuerst wird der linke Operand, lhs, ausgewertet und sein Ergebniswert verworfen.
Dann findet ein Sequenzpunkt statt, sodass alle Seiteneffekte von lhs abgeschlossen sind.
Dann wird der rechte Operand, rhs, ausgewertet und sein Ergebnis wird vom Komma-Operator als Nicht-Lvalue zurückgegeben.
[bearbeiten] Hinweise
Der Typ von lhs kann void sein (d. h. es kann sich um einen Aufruf einer Funktion handeln, die void zurückgibt, oder um einen Ausdruck, der nach void castet wurde)
Der Komma-Operator kann in C++ ein Lvalue sein, in C jedoch niemals
Der Komma-Operator kann eine Struktur zurückgeben (die einzigen anderen Ausdrücke, die Strukturen zurückgeben, sind zusammengesetzte Literale, Funktionsaufrufe, Zuweisungen und der bedingte Operator)
In den folgenden Kontexten kann der Komma-Operator nicht auf der obersten Ebene eines Ausdrucks auftreten, da das Komma eine andere Bedeutung hat
- Argumentliste in einem Funktionsaufruf
- Initialisierungsausdruck oder Initialisierungsliste
- generische Auswahl
Wenn der Komma-Operator in einem solchen Kontext verwendet werden muss, muss er in Klammern gesetzt werden
// int n = 2,3; // error, comma assumed to begin the next declarator // int a[2] = {1,2,3}; // error: more initializers than elements int n = (2,3), a[2] = {(1,2),3}; // OK f(a, (t=3, t+2), c); // OK, first, stores 3 in t, then calls f with three arguments
Der Komma-Operator auf der obersten Ebene ist auch in Array-Grenzen nicht zulässig
// int a[2,3]; // error int a[(2,3)]; // OK, VLA array of size 3 (VLA because (2,3) is not a constant expression)
Der Komma-Operator ist in konstanten Ausdrücken nicht erlaubt, unabhängig davon, ob er sich auf der obersten Ebene befindet oder nicht
// static int n = (1,2); // Error: constant expression cannot call the comma operator[bearbeiten] Cast-Operator
Siehe Cast-Operator
[bearbeiten] Bedingter Operator
Der Ausdruck des bedingten Operators hat die Form
Bedingung ? Ausdruck-wahr : Ausdruck-falsch |
|||||||||
wobei
| condition | - | ein Ausdruck von skalararem Typ |
| Ausdruck-wahr | - | der Ausdruck, der ausgewertet wird, wenn die Bedingung ungleich Null ist |
| Ausdruck-falsch | - | der Ausdruck, der ausgewertet wird, wenn die Bedingung gleich Null ist |
Nur die folgenden Ausdrücke sind als Ausdruck-wahr und Ausdruck-falsch zulässig
- zwei Ausdrücke von beliebigen arithmetischen Typen
- zwei Ausdrücke vom selben Struktur- oder Union-Typ
- zwei Ausdrücke vom Typ void
- zwei Ausdrücke vom Zeigertyp, die auf Typen zeigen, die kompatibel sind, wobei cvr-Qualifizierer ignoriert werden
|
(seit C23) |
- ein Ausdruck ist ein Zeiger und der andere ist die Nullzeigerkonstante (wie z. B. NULL)oder ein nullptr_t-Wert(seit C23)
- ein Ausdruck ist ein Zeiger auf ein Objekt und der andere ein Zeiger auf void (möglicherweise qualifiziert)
| (seit C23) |
#define ICE(x) (sizeof(*(1 ? ((void*)((x) * 0l)) : (int*)1))) // if x is an Integer Constant Expression then macro expands to sizeof(*(1 ? NULL : (int *) 1)) // (void *)((x)*0l)) -> NULL // according to point (4) this further converts into sizeof(int) // if x is not an Integer Constant Expression then macro expands to // according to point (6) (sizeof(*(void *)(x)) // Error due incomplete type
[bearbeiten] Hinweise
Der bedingte Operator ist niemals ein lvalue-Ausdruck, obwohl er Objekte vom Struktur-/Union-Typ zurückgeben kann. Die einzigen anderen Ausdrücke, die Strukturen zurückgeben können, sind Zuweisung, Komma, Funktionsaufruf und zusammengesetztes Literal.
Beachten Sie, dass er in C++ ein lvalue-Ausdruck sein kann.
Siehe Operatorrangfolge für Details zur relativen Rangfolge dieses Operators und der Zuweisung.
Der bedingte Operator hat eine Rechts-nach-Links-Assoziativität, die Verkettung ermöglicht
#include <assert.h> enum vehicle { bus, airplane, train, car, horse, feet }; enum vehicle choose(char arg) { return arg == 'B' ? bus : arg == 'A' ? airplane : arg == 'T' ? train : arg == 'C' ? car : arg == 'H' ? horse : feet ; } int main(void) { assert(choose('H') == horse && choose('F') == feet); }
[bearbeiten] sizeof-Operator
Siehe sizeof-Operator
[bearbeiten] _Alignof-Operator
Siehe _Alignof-Operator
[bearbeiten] typeof-Operatoren
Siehe typeof-Operatoren
[bearbeiten] Referenzen
- C23-Standard (ISO/IEC 9899:2024)
- 6.5.2.2 Funktionsaufrufe (S: TBD)
- 6.5.3.4 Die Operatoren sizeof und _Alignof (S: TBD)
- 6.5.4 Cast-Operatoren (S: TBD)
- 6.5.15 Bedingter Operator (S: TBD)
- 6.5.17 Komma-Operator (S: TBD)
- 6.7.3.5 Typeof-Spezifizierer (S: 115-118)
- C17-Standard (ISO/IEC 9899:2018)
- 6.5.2.2 Funktionsaufrufe (S: 58-59)
- 6.5.3.4 Die Operatoren sizeof und _Alignof (S: 64-65)
- 6.5.4 Cast-Operatoren (S: 65-66)
- 6.5.15 Bedingter Operator (S: 71-72)
- 6.5.17 Komma-Operator (S: 75)
- C11-Standard (ISO/IEC 9899:2011)
- 6.5.2.2 Funktionsaufrufe (S: 81-82)
- 6.5.3.4 The sizeof and _Alignof operators (p: 90-91)
- 6.5.4 Cast-Operatoren (S: 91)
- 6.5.15 Bedingter Operator (S: 100)
- 6.5.17 Komma-Operator (S: 105)
- C99-Standard (ISO/IEC 9899:1999)
- 6.5.2.2 Funktionsaufrufe (S: 71-72)
- 6.5.3.4 Der sizeof-Operator (S: 80-81)
- 6.5.4 Cast-Operatoren (S: 81)
- 6.5.15 Bedingter Operator (S: 90-91)
- 6.5.17 Komma-Operator (S: 94)
- C89/C90-Standard (ISO/IEC 9899:1990)
- 3.3.2.2 Funktionsaufrufe
- 3.3.3.4 Der sizeof-Operator
- 3.3.4 Cast-Operatoren
- 3.3.15 Bedingter Operator
- 3.3.17 Komma-Operator
[bearbeiten] Siehe auch
| Häufige Operatoren | ||||||
|---|---|---|---|---|---|---|
| Zuweisung | Inkrement Dekrement |
Arithmetik | Logisch | Vergleich | Member Zugriff |
Sonstiges |
|
a = b |
++a |
+a |
!a |
a == b |
a[b] |
a(...) |
| C++ Dokumentation für Andere Operatoren
|