Namespaces
Variants

Other operators

From cppreference.net

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

Operator Operatorname Beispiel Beschreibung
( ... ) Funktionsaufruf f ( ... ) ruft die Funktion f () auf, mit null oder mehr Argumenten
, Komma-Operator a, b wertet Ausdruck a aus, ignoriert dessen Rückgabewert und schließt alle Nebeneffekte ab, dann wertet Ausdruck b aus und gibt den Typ und das Ergebnis dieser Auswertung zurück
( type ) Typumwandlung ( type ) a wandelt den Typ von a zu type um
? : Bedingungsoperator a ? b : c wenn a logisch wahr ist (nicht zu Null auswertet), dann wertet Ausdruck b aus, andernfalls wertet Ausdruck c aus
sizeof sizeof-Operator sizeof a die Größe von a in Bytes
_Alignof
(seit C11)
_Alignof-Operator _Alignof ( type ) die erforderliche Ausrichtung von type
typeof typeof-Operatoren typeof ( a ) der Typ von a

Inhaltsverzeichnis

Funktionsaufruf

Der Funktionsaufrufausdruck hat die Form

Ausdruck ( Argumentenliste  (optional) )

wo

expression - beliebiger Ausdruck vom Typ Zeiger-auf-Funktion (nach Lvalue-Konvertierungen )
argument-list - kommagetrennte Liste von Ausdrücken (die keine Komma-Operatoren sein können) beliebiger vollständiger Objekttypen. Kann weggelassen werden beim Aufruf von Funktionen ohne Parameter.

Das Verhalten des Funktionsaufrufausdrucks hängt davon ab, ob der Prototyp der aufgerufenen Funktion im Gültigkeitsbereich am Aufrufort vorhanden ist.

Aufruf einer Funktion mit einem Prototyp

1) Die Anzahl der Parameter muss der Anzahl der Argumente entsprechen (sofern der Ellipsen-Parameter nicht verwendet wird).
2) Der Typ jedes Parameters muss ein Typ sein, für den implizite Konvertierung wie durch Zuweisung existiert, die den unqualifizierten Typ des entsprechenden Arguments in den Typ des Parameters umwandelt.
Zusätzlich muss für jeden Parameter vom Array-Typ , der das Schlüsselwort static zwischen [ und ] verwendet, der Argumentausdruck einen Zeiger auf ein Element eines Arrays bezeichnen, das mindestens so viele Elemente aufweist wie in der Größenangabe des Parameters spezifiziert.
(seit C99)
4) Zuweisung wird durchgeführt, um den Wert jedes Arguments in den entsprechenden Funktionsparameter zu kopieren, wobei jegliche Typqualifizierer des Parametertyps und seiner möglicherweise rekursiven Elemente oder Mitglieder ignoriert werden, falls vorhanden (Hinweis: Die Funktion kann ihre Parameter ändern, und diese Änderungen beeinflussen die Argumente nicht; C-Funktionsaufrufe sind ausschließlich Call-by-Value).
5) Die Funktion wird ausgeführt und der von ihr 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) Standardargument-Höherwertungen werden für jeden Argumentausdruck durchgeführt.
3) Zuweisung wird durchgeführt, um den Wert jedes Arguments an den entsprechenden Funktionsparameter zu kopieren, wobei etwaige Typqualifizierer auf dem Parametertyp und dessen möglichen rekursiven Elementen oder Mitgliedern ignoriert werden.
4) Die Funktion wird ausgeführt, und der von ihr 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 ohne Prototyp ist undefiniert, wenn

  • die Anzahl der Argumente nicht mit der Anzahl der Parameter übereinstimmt.
  • die höherwertigen Typen der Argumente nicht kompatibel mit den höherwertigen Typen der Parameter sind, außer dass
  • vorzeichenbehaftete und vorzeichenlose Versionen desselben Ganzzahltyps als kompatibel betrachtet werden, wenn der Wert des Arguments durch beide Typen darstellbar ist.
  • Zeiger auf void und Zeiger auf (möglicherweise cvr-qualifizierte) Zeichentypen als kompatibel betrachtet werden
(bis C23)

Hinweise

Die Auswertungen von expression , die die aufzurufende Funktion bezeichnen, und aller Argumente sind unsequenced zueinander (jedoch gibt es einen Sequence Point bevor der Rumpf der Funktion mit der Ausführung beginnt)

(*pf[f1()]) (f2(), f3() + f4()); // f1, f2, f3, f4 können in beliebiger Reihenfolge aufgerufen werden

Obwohl der Funktionsaufruf nur für Zeiger auf Funktionen definiert ist, funktioniert er mit Funktionsbezeichnern aufgrund der impliziten Funktion-zu-Zeiger-Konvertierung .

int f(void) { return 1; }
int (*pf)(void) = f;
int main(void)
{
    f();    // f in Zeiger konvertieren, dann aufrufen
    (&f)(); // Zeiger auf Funktion erstellen, dann aufrufen
    pf();    // Funktion aufrufen
    (*pf)(); // Funktionsbezeichner erhalten, in Zeiger konvertieren, dann aufrufen
    (****f)(); // In Zeiger konvertieren, Funktion erhalten, 4x wiederholen, dann aufrufen
    (****pf)(); // ebenfalls OK
}

Funktionen, die ungenutzte Argumente ignorieren, wie zum Beispiel printf , müssen mit einem Prototyp im Gültigkeitsbereich aufgerufen werden (der Prototyp solcher Funktionen verwendet notwendigerweise den nachgestellten Ellipsen -Parameter), um undefiniertes Verhalten zu vermeiden.

Die aktuelle Standardformulierung der Semantik zur Vorbereitung von Funktionsparametern ist fehlerhaft, da sie festlegt, dass Parameter beim Aufruf von Argumenten zugewiesen werden, was fälschlicherweise const-qualifizierte Parameter- oder Membertypen ablehnt und unangemessen die Semantik von volatile anwendet, die für Funktionsparameter auf vielen Plattformen nicht implementierbar ist. Ein Post-C11-Fehlerbericht DR427 schlug eine Änderung dieser Semantik von Zuweisung zu Initialisierung vor, wurde jedoch als kein Fehler geschlossen.

Ein Funktionsaufrufausdruck, bei dem expression vollständig aus einem Bezeichner besteht und dieser Bezeichner nicht deklariert ist, verhält sich so, als ob der Bezeichner deklariert wäre als

extern int identifier(); // returns int and has no prototype

Daher ist das folgende vollständige Programm gültiges C89:

main()
{
    int n = atoi("123"); // implicitly declares atoi as int atoi()
}
(bis C99)

Komma-Operator

Der Komma-Operator-Ausdruck hat die Form

lhs , rhs

wo

lhs - beliebiger Ausdruck
rhs - beliebiger Ausdruck außer einem weiteren Komma-Operator (mit anderen Worten, die Assoziativität des Komma-Operators ist links-nach-rechts)

Zuerst wird der linke Operand, lhs , ausgewertet und sein Ergebniswert verworfen.

Dann findet ein Sequenzpunkt statt, sodass alle Nebeneffekte von lhs abgeschlossen sind.

Dann wird der rechte Operand, rhs , ausgewertet und sein Ergebnis wird durch den Komma-Operator als ein Non-Lvalue zurückgegeben.

Hinweise

Der Typ des lhs kann void sein (das heißt, es kann sich um einen Aufruf einer Funktion handeln, die void zurückgibt, oder es kann ein Ausdruck sein, der durch eine Cast -Operation zu void umgewandelt wird)

Der Komma-Operator kann in C++ ein Lvalue sein, aber niemals in C

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 erscheinen, 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; // Fehler: Komma wird als Beginn des nächsten Deklarators angenommen
// int a[2] = {1,2,3}; // Fehler: Mehr Initialisierer als Elemente
int n = (2,3), a[2] = {(1,2),3}; // OK
f(a, (t=3, t+2), c); // OK, speichert zuerst 3 in t, ruft dann f mit drei Argumenten auf

Der Top-Level-Komma-Operator ist in Array-Grenzen ebenfalls nicht erlaubt

// int a[2,3]; // Fehler
int a[(2,3)]; // OK, VLA-Array der Größe 3 (VLA, da (2,3) kein konstanter Ausdruck ist)

Der Komma-Operator ist nicht erlaubt in konstanten Ausdrücken , unabhängig davon, ob er auf oberster Ebene steht oder nicht

// static int n = (1,2); // Fehler: Konstante Ausdrücke können den Komma-Operator nicht aufrufen

Cast-Operator

Siehe cast operator

Bedingter Operator

Der bedingte Operatorausdruck hat die Form

Bedingung ? Wahr-Ausdruck : Falsch-Ausdruck

wo

condition - ein Ausdruck skalaren Typs
expression-true - der Ausdruck, der ausgewertet wird, wenn condition ungleich Null verglichen wird
expression-false - der Ausdruck, der ausgewertet wird, wenn condition gleich Null verglichen wird

Nur die folgenden Ausdrücke sind als expression-true und expression-false erlaubt

  • zwei Ausdrücke beliebigen arithmetischen Typs
  • zwei Ausdrücke desselben struct - oder union -Typs
  • zwei Ausdrücke vom void-Typ
  • zwei Ausdrücke vom Zeigertyp, die auf Typen zeigen, die kompatibel sind, unter Ignorierung von CVR-Qualifizierern
(seit C23)
  • ein Ausdruck ist ein Zeiger und der andere ist die Nullzeiger-Konstante (wie NULL ) oder ein nullptr_t -Wert (seit C23)
  • ein Ausdruck ist ein Zeiger auf Objekt und der andere ist ein Zeiger auf void (möglicherweise qualifiziert)
1) Zuerst wird die condition ausgewertet. Danach folgt ein sequence point .
2) Wenn das Ergebnis von condition ungleich Null vergleicht, wird expression-true ausgeführt, andernfalls wird expression-false ausgeführt
3) Führt eine Konvertierung vom Ergebnis der Auswertung zum gemeinsamen Typ durch, definiert wie folgt:
1) wenn die Ausdrücke arithmetischen Typ haben, ist der gemeinsame Typ der Typ nach den usual arithmetic conversions
2) wenn die Ausdrücke Struktur-/Union-Typ haben, ist der gemeinsame Typ dieser Struktur-/Union-Typ
3) wenn beide Ausdrücke void sind, ist der gesamte Bedingungsoperator-Ausdruck ein void-Ausdruck
4) wenn einer ein Zeiger und der andere eine Nullzeiger-Konstante oder ein nullptr_t Wert (seit C23) ist, dann 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 gezeigter Typen kombiniert (das heißt, wenn einer const int * und der andere volatile int * ist, ist das Ergebnis const volatile int * ), und wenn die Typen unterschiedlich waren, ist der gezeigte 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 den Typ nullptr_t haben, ist der gemeinsame Typ ebenfalls nullptr_t
(seit C23)
#define ICE(x) (sizeof(*(1 ? ((void*)((x) * 0l)) : (int*)1)))
// falls x ein Integer-Konstantenausdruck ist, dann expandiert das Makro zu
sizeof(*(1 ? NULL : (int *) 1))  // (void *)((x)*0l)) -> NULL
// gemäß Punkt (4) konvertiert dies weiter in
sizeof(int)
// falls x kein Integer-Konstantenausdruck ist, dann expandiert das Makro zu
// gemäß Punkt (6)
(sizeof(*(void *)(x))           // Fehler aufgrund unvollständigen Typs

Hinweise

Der bedingte Operator ist niemals ein Lvalue-Ausdruck , obwohl er Objekte vom Typ Struct/Union zurückgeben kann. Die einzigen anderen Ausdrücke, die Structs zurückgeben können, sind Zuweisung , Komma , Funktionsaufruf und zusammengesetztes Literal .

Beachten Sie, dass es sich in C++ um einen Lvalue-Ausdruck handeln kann.

Siehe Operator-Präzedenz für Details zur relativen Priorität dieses Operators und Zuweisung.

Der bedingte Operator hat Rechts-nach-links-Assoziativität, was 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);
}

sizeof Operator

Siehe sizeof-Operator

_Alignof Operator

Siehe _Alignof operator

typeof Operatoren

Siehe typeof-Operatoren

Referenzen

  • C23-Standard (ISO/IEC 9899:2024):
  • 6.5.2.2 Funktionsaufrufe (S: TBD)
  • 6.5.3.4 Die sizeof- und _Alignof-Operatoren (S: TBD)
  • 6.5.4 Typumwandlungsoperatoren (S: TBD)
  • 6.5.15 Bedingungsoperator (S: TBD)
  • 6.5.17 Kommaoperator (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 sizeof- und _Alignof-Operatoren (S: 64-65)
  • 6.5.4 Typumwandlungsoperatoren (S: 65-66)
  • 6.5.15 Bedingungsoperator (S: 71-72)
  • 6.5.17 Kommaoperator (S: 75)
  • C11-Standard (ISO/IEC 9899:2011):
  • 6.5.2.2 Funktionsaufrufe (S: 81-82)
  • 6.5.3.4 Die sizeof- und _Alignof-Operatoren (S: 90-91)
  • 6.5.4 Typumwandlungsoperatoren (S: 91)
  • 6.5.15 Bedingungsoperator (S: 100)
  • 6.5.17 Kommaoperator (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 Typumwandlungsoperatoren (S. 81)
  • 6.5.15 Bedingungsoperator (S. 90-91)
  • 6.5.17 Kommaoperator (S. 94)
  • C89/C90-Standard (ISO/IEC 9899:1990):
  • 3.3.2.2 Funktionsaufrufe
  • 3.3.3.4 Der sizeof-Operator
  • 3.3.4 Typumwandlungsoperatoren
  • 3.3.15 Bedingungsoperator
  • 3.3.17 Kommaoperator

Siehe auch

Häufige Operatoren
Zuweisung Inkrement
Dekrement
Arithmetisch Logisch Vergleich Mitgliederzugriff
Zugriff
Sonstige

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