Namensräume
Varianten
Aktionen

Andere Operatoren

Von cppreference.com
< c‎ | Sprache

Eine Sammlung von Operatoren, die in keine der anderen Hauptkategorien passen.

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

1) Die Anzahl der Parameter muss der Anzahl der Argumente entsprechen (es sei denn, der Ellipsenparameter wird verwendet).
2) Der Typ jedes Parameters muss ein Typ sein, für den eine implizite Konvertierung wie durch Zuweisung existiert, die den nicht qualifizierten Typ des entsprechenden Arguments in den Typ des Parameters konvertiert.
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)
4) 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 (Hinweis: Die Funktion kann ihre Parameter ändern, und diese Änderungen wirken sich nicht auf die Argumente aus; C-Funktionsaufrufe sind nur Call-by-Value).
5) 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(char* p, int x) {}
int main(void)
{
    f("abc", 3.14); // array to pointer and float to int conversions
}

Aufruf einer Funktion ohne Prototyp

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

  • die Anzahl der Argumente nicht mit der Anzahl der Parameter übereinstimmt.
  • die getrennten Typen der Argumente nicht kompatibel mit den getrennten Typen der Parameter sind, außer dass
  • signed und unsigned Versionen desselben Ganzzahltyps als kompatibel gelten, wenn der Wert des Arguments von beiden Typen dargestellt werden kann.
  • Zeiger auf void und Zeiger auf (möglicherweise cvr-qualifizierte) Zeichentypen gelten als kompatibel
(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

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)
1) Zuerst wird Bedingung ausgewertet. Nach dieser Auswertung findet ein Sequenzpunkt statt.
2) Wenn das Ergebnis von Bedingung ungleich Null ist, wird Ausdruck-wahr ausgeführt, andernfalls wird Ausdruck-falsch ausgeführt.
3) Es wird eine Konvertierung vom Ergebnis der Auswertung zum *gemeinsamen Typ* durchgeführt, der wie folgt definiert ist:
1) wenn die Ausdrücke einen arithmetischen Typ haben, ist der gemeinsame Typ der Typ nach üblichen arithmetischen Konvertierungen
2) wenn die Ausdrücke einen Struktur-/Union-Typ haben, ist der gemeinsame Typ dieser Struktur-/Union-Typ
3) wenn die Ausdrücke beide void sind, ist der gesamte Ausdruck des bedingten Operators ein void-Ausdruck
4) wenn einer ein Zeiger und der andere eine Nullzeigerkonstante istoder ein nullptr_t-Wert(seit C23), ist der Typ der Typ dieses Zeigers
5) wenn beide Zeiger sind, ist das Ergebnis der Zeiger auf den Typ, der die cvr-Qualifizierer beider adressierter Typen kombiniert (d. h. wenn einer const int* und der andere volatile int* ist, ist das Ergebnis const volatile int*), und wenn die Typen unterschiedlich wären, ist der adressierte Typ der zusammengesetzte Typ.
6) wenn einer ein Zeiger auf void ist, ist das Ergebnis ein Zeiger auf void mit kombinierten cvr-Qualifizierern
7) wenn beide vom Typ nullptr_t sind, ist der gemeinsame Typ ebenfalls nullptr_t
(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 += b
a -= b
a *= b
a /= b
a %= b
a &= b
a |= b
a ^= b
a <<= b
a >>= b

++a
--a
a++
a--

+a
-a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b

!a
a && b
a || b

a == b
a != b
a < b
a > b
a <= b
a >= b

a[b]
*a
&a
a->b
a.b

a(...)
a, b
(type) a
a ? b : c
sizeof


_Alignof
(seit C11)
(bis C23)

alignof
(seit C23)

C++ Dokumentation für Andere Operatoren