Namensräume
Varianten
Aktionen

Arithmetische Operatoren

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

Gibt das Ergebnis einer bestimmten arithmetischen Operation zurück.

Operatorname Syntax Prototypenbeispiele (für class T)
Innerhalb der Klassendefinition Außerhalb der Klassendefinition
Unärer Plusoperator +a T T::operator+() const; T operator+(const T& a);
Unärer Minusoperator -a T T::operator-() const; T operator-(const T& a);
Addition a + b T T::operator+(const T2& b) const; T operator+(const T& a, const T2& b);
Subtraktion a - b T T::operator-(const T2& b) const; T operator-(const T& a, const T2& b);
Multiplikation a * b T T::operator*(const T2& b) const; T operator*(const T& a, const T2& b);
Division a / b T T::operator/(const T2& b) const; T operator/(const T& a, const T2& b);
Rest a % b T T::operator%(const T2& b) const; T operator%(const T& a, const T2& b);
Bitweises NICHT ~a T T::operator~() const; T operator~(const T& a);
Bitweises UND a & b T T::operator&(const T2& b) const; T operator&(const T& a, const T2& b);
Bitweises ODER a | b T T::operator|(const T2& b) const; T operator|(const T& a, const T2& b);
Bitweises XOR a ^ b T T::operator^(const T2& b) const; T operator^(const T& a, const T2& b);
Bitweises Links-Shift a << b T T::operator<<(const T2& b) const; T operator<<(const T& a, const T2& b);
Bitweises Rechts-Shift a >> b T T::operator>>(const T2& b) const; T operator>>(const T& a, const T2& b);
Anmerkungen
  • Alle Operatoren in dieser Tabelle sind überladbar.
  • Alle integrierten Operatoren geben Werte zurück, und die meisten benutzerdefinierten Überladungen geben ebenfalls Werte zurück, sodass die benutzerdefinierten Operatoren auf die gleiche Weise wie die integrierten verwendet werden können. In einer benutzerdefinierten Operatorüberladung kann jedoch jeder Typ als Rückgabetyp verwendet werden (einschließlich void). Insbesondere geben Stream-Einfüge- und Stream-Extraktionsüberladungen von operator<< und operator>> T& zurück.
  • T2 kann jeder Typ sein, einschließlich T.

Inhalt

[edit] Allgemeine Erklärung

Alle integrierten arithmetischen Operatoren berechnen das Ergebnis einer bestimmten arithmetischen Operation und geben ihr Ergebnis zurück. Die Argumente werden nicht geändert.

[edit] Umwandlungen

Wenn der Operand, der an einen integrierten arithmetischen Operator übergeben wird, ein ganzzahliger oder nicht-aufgezählter Enumerationstyp ist, dann wird er vor jeder anderen Aktion (aber nach der L-Wert-zu-R-Wert-Konvertierung, falls zutreffend) einer Ganzzahl-Promotion unterzogen. Wenn ein Operand einen Array- oder Funktionstyp hat, werden Array-zu-Zeiger- und Funktion-zu-Zeiger-Konvertierungen angewendet.

Für die binären Operatoren (außer Shifts) werden, wenn die getreppten Operanden unterschiedliche Typen haben, die üblichen arithmetischen Konvertierungen angewendet.

[edit] Überläufe

Vorzeichenlose Ganzzahlarithmetik wird immer modulo 2n
ausgeführt, wobei n die Anzahl der Bits in dieser bestimmten Ganzzahl ist. Z. B. für unsigned int ergibt das Hinzufügen von eins zu UINT_MAX 0, und das Subtrahieren von eins von 0 ergibt UINT_MAX.

Wenn bei der vorzeichenbehafteten Ganzzahlarithmetik ein Überlauf auftritt (das Ergebnis passt nicht in den Ergebnistyp), ist das Verhalten undefiniert — mögliche Manifestationen einer solchen Operation sind

  • sie schlägt nach den Regeln der Darstellung um (typischerweise Zweierkomplement),
  • sie löst eine Ausnahme aus — auf einigen Plattformen oder aufgrund von Compiler-Optionen (z. B. -ftrapv in GCC und Clang),
  • sie sättigt auf den minimalen oder maximalen Wert (auf vielen DSPs),
  • sie wird vom Compiler vollständig optimiert.

[edit] Gleitkommaumgebung

Wenn #pragma STDC FENV_ACCESS unterstützt wird und auf ON gesetzt ist, gehorchen alle Gleitkommaarithmetikoperatoren der aktuellen Gleitkomma- Rundungsrichtung und melden Gleitkommaarithmetikfehler wie in math_errhandling angegeben, es sei denn, sie sind Teil eines statischen Initialisierers (in diesem Fall werden keine Gleitkommaausnahmen ausgelöst und die Rundungsmodus ist auf "nächstliegend" gesetzt).

[edit] Gleitkomma-Kontraktion

Sofern #pragma STDC FP_CONTRACT nicht unterstützt und auf OFF gesetzt ist, kann die gesamte Gleitkommaarithmetik so ausgeführt werden, als hätten die Zwischenergebnisse unendliche Reichweite und Präzision, d. h., es sind Optimierungen zulässig, die Rundungsfehler und Gleitkommaausnahmen weglassen. Zum Beispiel erlaubt C++ die Implementierung von (x * y) + z mit einer einzigen fused multiply-add CPU-Instruktion oder die Optimierung von a = x * x * x * x; als tmp = x * x; a = tmp * tmp.

Unabhängig von der Kontraktion können Zwischenergebnisse der Gleitkommaarithmetik eine Reichweite und Präzision haben, die sich von der durch ihren Typ angezeigten unterscheidet; siehe FLT_EVAL_METHOD.

Formal garantiert der C++-Standard keine Genauigkeit von Gleitkommaoperationen.

[edit] Unäre arithmetische Operatoren

Die Ausdrücke unärer arithmetischer Operatoren haben die Form

+ Ausdruck (1)
- Ausdruck (2)
1) Unärer Plusoperator (Promotion).
2) Unärer Minusoperator (Negation).

Die unären Operatoren + und - haben eine höhere Rangfolge als alle binären arithmetischen Operatoren, daher kann Ausdruck keine binären arithmetischen Operatoren auf oberster Ebene enthalten. Diese Operatoren assoziieren von rechts nach links.

+a - b; // equivalent to (+a) - b, NOT +(a - b)
-c + d; // equivalent to (-c) + d, NOT -(c + d)
 
+-e; // equivalent to +(-e), the unary + is a no-op if “e” is a built-in type
     // because any possible promotion is performed during negation already

[edit] Integrierte unäre arithmetische Operatoren

1) Für den integrierten unären Plusoperator muss Ausdruck ein prvalue eines arithmetischen, nicht-aufgezählten Enumerationstyps oder Zeigertyps sein. Eine Ganzzahl-Promotion wird auf Ausdruck angewendet, wenn dieser einen Ganzzahl- oder nicht-aufgezählten Enumerationstyp hat. Der Typ des Ergebnisses ist der (möglicherweise getreppte) Typ von Ausdruck.
Das Ergebnis der integrierten Promotion ist der Wert von Ausdruck. Die integrierte unäre Operation ist eine No-Operation, wenn der Operand ein prvalue eines getreppten Ganzzahltyps oder eines Zeigertyps ist. Andernfalls wird der Typ oder die Wertkategorie des Operanden durch Ganzzahl-Promotion oder L-Wert-zu-R-Wert-, Array-zu-Zeiger-, Funktion-zu-Zeiger- oder benutzerdefinierte Konvertierung geändert. Zum Beispiel wird char in int konvertiert , und nicht-generische, keine Lambda-Ausdrücke ohne Capture werden in Funktionszeiger konvertiert(seit C++11) in unären Plusausdrücken.
2) Für den integrierten unären Minusoperator muss Ausdruck ein prvalue eines arithmetischen oder nicht-aufgezählten Enumerationstyps sein. Eine Ganzzahl-Promotion wird auf Ausdruck angewendet. Der Typ des Ergebnisses ist der Typ des getreppten Typs von Ausdruck.
Das Ergebnis der integrierten Negation ist das Negative des getreppten Ausdrucks. Für vorzeichenlose a ist der Wert von -a 2N
-a
, wobei N die Anzahl der Bits nach der Promotion ist.
  • Mit anderen Worten: Das Ergebnis ist das Zweierkomplement des Operanden (wobei Operand und Ergebnis als vorzeichenlos betrachtet werden).

[edit] Überladungen

Bei der Überladungsauflösung gegen benutzerdefinierte Operatoren nehmen für jeden cv-unqualifizierten getreppten arithmetischen Typ A und für jeden Typ T die folgenden Funktionssignaturen an der Überladungsauflösung teil

A operator+(A)
T* operator+(T*)
A operator-(A)
#include <iostream>
 
int main()
{
    char c = 0x6a;
    int n1 = 1;
    unsigned char n2 = 1;
    unsigned int n3 = 1;
    std::cout << "char: " << c << " int: " << +c << "\n"
                 "-1, where 1 is signed: " << -n1 << "\n"
                 "-1, where 1 is unsigned char: " << -n2 << "\n"
                 "-1, where 1 is unsigned int: " << -n3 << '\n';
    char a[3];
    std::cout << "size of array: " << sizeof a << "\n"
                 "size of pointer: " << sizeof +a << '\n';
}

Mögliche Ausgabe

char: j int: 106
-1, where 1 is signed: -1
-1, where 1 is unsigned char: -1
-1, where 1 is unsigned int: 4294967295
size of array: 3
size of pointer: 8

[edit] Additive Operatoren

Die Ausdrücke additiver Operatoren haben die Form

lhs + rhs (1)
lhs - rhs (2)
1) Binäres Plus (Addition).
2) Binäres Minus (Subtraktion).

Die binären Operatoren + und - haben eine höhere Rangfolge als alle anderen binären arithmetischen Operatoren außer *, / und %. Diese Operatoren assoziieren von links nach rechts.

a + b * c;  // equivalent to a + (b * c),  NOT (a + b) * c
d / e - f;  // equivalent to (d / e) - f,  NOT d / (e - f)
g + h >> i; // equivalent to (g + h) >> i, NOT g + (h >> i)
 
j - k + l - m; // equivalent to ((j - k) + l) - m

[edit] Integrierte additive Operatoren

Für integrierte binäre Plus- und binäre Minusoperatoren müssen beide Operanden prvalues sein und eine der folgenden Bedingungen muss erfüllt sein

  • Beide Operanden haben einen arithmetischen oder nicht-aufgezählten Enumerationstyp. In diesem Fall werden für beide Operanden die üblichen arithmetischen Konvertierungen angewendet.
  • Genau ein Operand hat einen Ganzzahl- oder nicht-aufgezählten Enumerationstyp. In diesem Fall wird eine Ganzzahl-Promotion auf diesen Operanden angewendet.

In der verbleibenden Beschreibung in diesem Abschnitt beziehen sich "Operand(en)", lhs und rhs auf die konvertierten oder getreppten Operanden.

1) Für die integrierte Addition muss eine der folgenden Bedingungen erfüllt sein
  • Beide Operanden haben einen arithmetischen Typ. In diesem Fall ist das Ergebnis die Summe der Operanden.
  • Ein Operand ist ein Zeiger auf einen vollständig definierten Objekttyp, und der andere Operand hat einen ganzzahligen Typ. In diesem Fall wird der ganzzahlige Wert zum Zeiger addiert (siehe Zeigerarithmetik).
2) Für die integrierte Subtraktion muss eine der folgenden Bedingungen erfüllt sein
  • Beide Operanden haben einen arithmetischen Typ. In diesem Fall ist das Ergebnis die Differenz, die sich aus der Subtraktion von rhs von lhs ergibt.
  • lhs ist ein Zeiger auf einen vollständig definierten Objekttyp, und rhs hat einen ganzzahligen Typ. In diesem Fall wird der ganzzahlige Wert vom Zeiger subtrahiert (siehe Zeigerarithmetik).
  • Beide Operanden sind Zeiger auf cv-qualifizierte oder cv-unqualifizierte Versionen desselben vollständig definierten Objekttyps. In diesem Fall wird rhs von lhs subtrahiert (siehe Zeigerarithmetik).

Wenn beide Operanden einen Gleitkommatyp haben und der Typ IEEE-Gleitkommaarithmetik unterstützt (siehe std::numeric_limits::is_iec559)

  • Wenn ein Operand NaN ist, ist das Ergebnis NaN.
  • Unendlichkeit minus Unendlichkeit ist NaN, und FE_INVALID wird ausgelöst.
  • Unendlichkeit plus die negative Unendlichkeit ist NaN, und FE_INVALID wird ausgelöst.

[edit] Zeigerarithmetik

Wenn ein Ausdruck J, der einen ganzzahligen Typ hat, zu einem Ausdruck P vom Zeigertyp addiert oder subtrahiert wird, hat das Ergebnis den Typ von P.

  • Wenn P zu einem Nullzeigerwert ausgewertet wird und J zu 0 ausgewertet wird, ist das Ergebnis ein Nullzeigerwert.
  • Andernfalls, wenn P auf das i-te Element eines Array-Objekts x mit n Elementen zeigt, gegeben den Wert von J als j, wird P wie folgt addiert oder subtrahiert
  • Die Ausdrücke P + J und J + P
  • zeigen auf das i+j-te Element von x, wenn i + j im Bereich [0n) liegt, und
  • zeigen auf die Position nach dem letzten Element von x, wenn i + j gleich n ist.
  • Der Ausdruck P - J
  • zeigt auf das i-j-te Element von x, wenn i - j im Bereich [0n) liegt, und
  • zeigt auf die Position nach dem letzten Element von x, wenn i - j gleich n ist.
  • Andere j-Werte führen zu undefiniertem Verhalten.
  • Andernfalls, wenn P auf ein vollständiges Objekt, ein Basisklassen-Teilobjekt oder ein Mitgliedsobjekt y zeigt, gegeben den Wert von J als j, wird P wie folgt addiert oder subtrahiert
  • Die Ausdrücke P + J und J + P
  • zeigt auf y, wenn j gleich 0 ist, und
  • zeigt auf die Position nach y, wenn j gleich 1 ist.
  • Der Ausdruck P - J
  • zeigt auf y, wenn j gleich 0 ist, und
  • zeigt auf die Position nach y, wenn j gleich -1 ist.
  • Andere j-Werte führen zu undefiniertem Verhalten.
  • Andernfalls, wenn P ein Zeiger auf die Position nach einem Objekt z ist, gegeben den Wert von J als j
  • Wenn z ein Array-Objekt mit n Elementen ist, wird P wie folgt addiert oder subtrahiert
  • Die Ausdrücke P + J und J + P
  • zeigt auf das n+j-te Element von z, wenn n + j im Bereich [0n) liegt, und
  • zeigt auf die Position nach dem letzten Element von z, wenn j gleich 0 ist.
  • Der Ausdruck P - J
  • zeigt auf das n-j-te Element von z, wenn n - j im Bereich [0n) liegt, und
  • zeigt auf die Position nach dem letzten Element von z, wenn j gleich 0 ist.
  • Andere j-Werte führen zu undefiniertem Verhalten.
  • Andernfalls wird P wie folgt addiert oder subtrahiert
  • Die Ausdrücke P + J und J + P
  • zeigt auf z, wenn j gleich -1 ist, und
  • zeigt auf die Position nach z, wenn j gleich 0 ist.
  • Der Ausdruck P - J
  • zeigt auf z, wenn j gleich 1 ist, und
  • zeigt auf die Position nach z, wenn j gleich 0 ist.
  • Andere j-Werte führen zu undefiniertem Verhalten.
  • Andernfalls ist das Verhalten undefiniert.

Wenn zwei Zeigerausdrücke P und Q subtrahiert werden, ist der Typ des Ergebnisses std::ptrdiff_t.

  • Wenn P und Q beide zu Nullzeigerwerten ausgewertet werden, ist das Ergebnis 0.
  • Andernfalls, wenn P und Q auf das i-te bzw. j-te Array-Element desselben Array-Objekts x zeigen, hat der Ausdruck P - Q den Wert i − j.
  • Wenn i − j nicht durch std::ptrdiff_t darstellbar ist, ist das Verhalten undefiniert.
  • Andernfalls, wenn P und Q auf dasselbe vollständige Objekt, Basisklassen-Teilobjekt oder Mitgliedsobjekt zeigen, ist das Ergebnis 0.
  • Andernfalls ist das Verhalten undefiniert.

Diese Zeigerarithmetikoperatoren ermöglichen es Zeigern, die Anforderungen des LegacyRandomAccessIterator zu erfüllen.

Bei Addition und Subtraktion ist das Verhalten undefiniert, wenn P oder Q den Typ "Zeiger auf (möglicherweise cv-qualifiziertes) T" hat, wobei T und der Array-Elementtyp nicht ähnlich sind.

int arr[5] = {1, 2, 3, 4, 5};
unsigned int *p = reinterpret_cast<unsigned int*>(arr + 1);
unsigned int k = *p; // OK, the value of “k” is 2
unsigned int *q = p + 1; // undefined behavior: “p” points to int, not unsigned int

[edit] Überladungen

Bei der Überladungsauflösung gegen benutzerdefinierte Operatoren nehmen für jedes Paar von getreppten arithmetischen Typen L und R und für jeden Objekttyp T die folgenden Funktionssignaturen an der Überladungsauflösung teil

LR operator+(L, R)
LR operator-(L, R)
T* operator+(T*, std::ptrdiff_t)
T* operator+(std::ptrdiff_t, T*)
T* operator-(T*, std::ptrdiff_t)
std::ptrdiff_t operator-(T*, T*)

wobei LR das Ergebnis der üblichen arithmetischen Konvertierungen von L und R ist.

#include <iostream>
 
int main()
{
    char c = 2;
    unsigned int un = 2;
    int n = -10;
    std::cout << " 2 + (-10), where 2 is a char    = " << c + n << "\n"
                 " 2 + (-10), where 2 is unsigned  = " << un + n << "\n"
                 " -10 - 2.12  = " << n - 2.12 << '\n';
 
    char a[4] = {'a', 'b', 'c', 'd'};
    char* p = &a[1];
    std::cout << "Pointer addition examples: " << *p << *(p + 2)
              << *(2 + p) << *(p - 1) << '\n';
    char* p2 = &a[4];
    std::cout << "Pointer difference: " << p2 - p << '\n';
}

Ausgabe

 2 + (-10), where 2 is a char    = -8
 2 + (-10), where 2 is unsigned  = 4294967288
 -10 - 2.12  = -12.12
Pointer addition examples: bdda
Pointer difference: 3

[edit] Multiplikative Operatoren

Die Ausdrücke multiplikativer Operatoren haben die Form

lhs * rhs (1)
lhs / rhs (2)
lhs % rhs (3)
1) Multiplikation.
2) Division.
3) Rest.

Multiplikative Operatoren haben eine höhere Rangfolge als alle anderen binären arithmetischen Operatoren. Diese Operatoren assoziieren von links nach rechts.

a + b * c;  // equivalent to a + (b * c),  NOT (a + b) * c
d / e - f;  // equivalent to (d / e) - f,  NOT d / (e - f)
g % h >> i; // equivalent to (g % h) >> i, NOT g % (h >> i)
 
j * k / l % m; // equivalent to ((j * k) / l) % m

[edit] Integrierte multiplikative Operatoren

Für integrierte Multiplikations- und Divisionsoperatoren müssen beide Operanden einen arithmetischen oder nicht-aufgezählten Enumerationstyp haben. Für den integrierten Restoperator müssen beide Operanden einen Ganzzahl- oder nicht-aufgezählten Enumerationstyp haben. Für beide Operanden werden übliche arithmetische Konvertierungen angewendet.

In der verbleibenden Beschreibung in diesem Abschnitt beziehen sich "Operand(en)", lhs und rhs auf die konvertierten Operanden.

1) Das Ergebnis der integrierten Multiplikation ist das Produkt der Operanden.
Wenn beide Operanden einen Gleitkommatyp haben und der Typ IEEE-Gleitkommaarithmetik unterstützt (siehe std::numeric_limits::is_iec559)
  • Die Multiplikation einer NaN mit einer beliebigen Zahl ergibt NaN.
  • Die Multiplikation einer Unendlichkeit mit Null ergibt NaN und FE_INVALID wird ausgelöst.
2) Das Ergebnis der integrierten Division ist lhs geteilt durch rhs. Wenn rhs Null ist, ist das Verhalten undefiniert.
Wenn beide Operanden einen ganzzahligen Typ haben, ist das Ergebnis der algebraische Quotient (führt Ganzzahldivision durch): Der Quotient wird gegen Null abgeschnitten (der gebrochene Teil wird verworfen).
Wenn beide Operanden einen Gleitkommatyp haben und der Typ IEEE-Gleitkommaarithmetik unterstützt (siehe std::numeric_limits::is_iec559)
  • Wenn ein Operand NaN ist, ist das Ergebnis NaN.
  • Das Dividieren einer Zahl ungleich Null durch ±0,0 ergibt die korrekt vorzeichenbehaftete Unendlichkeit und FE_DIVBYZERO wird ausgelöst.
  • Das Dividieren von 0,0 durch 0,0 ergibt NaN und FE_INVALID wird ausgelöst.
3) Das Ergebnis des eingebauten Restoperators ist der Rest der ganzzahligen Division von lhs durch rhs. Wenn rhs Null ist, ist das Verhalten undefiniert.
Wenn a / b im Ergebnistyp darstellbar ist, gilt (a / b) * b + a % b == a.
Wenn a / b nicht im Ergebnistyp darstellbar ist, ist das Verhalten sowohl von a / b als auch von a % b undefiniert (das bedeutet, INT_MIN % -1 ist auf Zweierkomplement-Systemen undefiniert).

Hinweis: Bis zur Behebung des CWG-Problems 614 (N2757) war das Vorzeichen des Rests implementierungsabhängig, wenn einer oder beide Operanden des binären Operators  % negativ waren, da es von der Rundungsrichtung der ganzzahligen Division abhing. Die Funktion std::div lieferte in diesem Fall ein wohldefiniertes Verhalten.

Hinweis: Für den Gleitkomma-Rest siehe std::remainder und std::fmod.

[edit] Überladungen

Bei der Überladungsauflösung für benutzerdefinierte Operatoren nehmen für jedes Paar von beförderten arithmetischen Typen LA und RA sowie für jedes Paar von beförderten ganzzahligen Typen LI und RI die folgenden Funktionssignaturen an der Überladungsauflösung teil:

LRA operator*(LA, RA)
LRA operator/(LA, RA)
LRI operator%(LI, RI)

wobei LRx das Ergebnis der gewöhnlichen arithmetischen Konvertierungen von Lx und Rx ist.

#include <iostream>
 
int main()
{
    char c = 2;
    unsigned int un = 2;
    int  n = -10;
    std::cout << "2 * (-10), where 2 is a char    = " << c * n << "\n"
                 "2 * (-10), where 2 is unsigned  = " << un * n << "\n"
                 "-10 / 2.12  = " << n / 2.12 << "\n"
                 "-10 / 21  = " << n / 21 << "\n"
                 "-10 % 21  = " << n % 21 << '\n';
}

Ausgabe

2 * (-10), where 2 is a char    = -20
2 * (-10), where 2 is unsigned  = 4294967276
-10 / 2.12  = -4.71698
-10 / 21  = 0
-10 % 21  = -10

[edit] Bitweise logische Operatoren

Die Ausdrücke der bitweisen logischen Operatoren haben die Form:

~ rhs (1)
lhs & rhs (2)
lhs | rhs (3)
lhs ^ rhs (4)
1) Bitweise NICHT.
2) Bitweise UND.
3) Bitweise ODER.
4) Bitweise XOR.

Der bitweise NICHT-Operator hat eine höhere Präzedenz als alle binären arithmetischen Operatoren. Er assoziiert von rechts nach links.

~a - b; // equivalent to (~a) - b, NOT ~(a - b)
~c * d; // equivalent to (~c) * d, NOT ~(c * d)
 
~-e; // equivalent to ~(-e)

Es gibt eine Mehrdeutigkeit in der Grammatik, wenn auf ~ ein Typname oder ein decltype-Spezifizierer(seit C++11) folgt: Es kann entweder operator~ sein oder einen Destruktor-Identifikator einleiten. Die Mehrdeutigkeit wird aufgelöst, indem ~ als operator~ behandelt wird. ~ kann nur dort einen Destruktor-Identifikator einleiten, wo die Bildung eines operator~ syntaktisch ungültig ist.

Alle anderen bitweisen logischen Operatoren haben eine geringere Präzedenz als alle anderen binären arithmetischen Operatoren. Bitweises UND hat eine höhere Präzedenz als bitweises XOR, welches eine höhere Präzedenz als bitweises ODER hat. Sie assoziieren von links nach rechts.

a & b * c;  // equivalent to a & (b * c),  NOT (a & b) * c
d / e ^ f;  // equivalent to (d / e) ^ f,  NOT d / (e ^ f)
g << h | i; // equivalent to (g << h) | i, NOT g << (h | i)
 
j & k & l; // equivalent to (j & k) & l
m | n ^ o  // equivalent to m | (n ^ o)

[edit] Eingebaute bitweise logische Operatoren

Für den eingebauten bitweisen NICHT-Operator muss rhs ein prvalue vom ganzzahligen oder nicht-aufgezählten Enumerationstyp sein, und eine ganzzahlige Promotion wird für rhs durchgeführt. Für andere eingebaute bitweise logische Operatoren müssen beide Operanden vom ganzzahligen oder nicht-aufgezählten Enumerationstyp sein, und gewöhnliche arithmetische Konvertierungen werden für beide Operanden durchgeführt.

In der verbleibenden Beschreibung in diesem Abschnitt beziehen sich "Operand(en)", lhs und rhs auf die konvertierten oder getreppten Operanden.

1) Gegeben den Operanden als x und das Ergebnis der eingebauten bitweisen NICHT-Operation als r. Für jeden Koeffizienten x_i der Basis-2-Darstellung von x ist der entsprechende Koeffizient r_i der Basis-2-Darstellung von r 1, wenn x_i 0 ist, und 0 andernfalls.
  • Mit anderen Worten, das Ergebnis ist das Einerkomplement des Operanden (wobei Operand und Ergebnis als vorzeichenlos betrachtet werden).
Der Typ des Ergebnisses r ist der Typ des Operanden x.
2-4) Gegeben die Operanden als x bzw. y und das Ergebnis der eingebauten binären bitweisen logischen Operationen als r. Für jedes Koeffizientenpaar x_i und y_i der Basis-2-Darstellungen von x bzw. y ist der entsprechende Koeffizient r_i der Basis-2-Darstellung von r:
2) 1, wenn sowohl x_i als auch y_i 1 sind, und 0 andernfalls.
3) 1, wenn mindestens einer von x_i und y_i 1 ist, und 0 andernfalls.
4) 1, wenn entweder (aber nicht beide) von x_i und y_i 1 ist, und 0 andernfalls.
Der Typ des Ergebnisses r ist der Typ der Operanden x und y.

[edit] Überladungen

Bei der Überladungsauflösung für benutzerdefinierte Operatoren nehmen für jedes Paar von beförderten ganzzahligen Typen L und R die folgenden Funktionssignaturen an der Überladungsauflösung teil:

R operator~(R)
LR operator&(L, R)
LR operator^(L, R)
LR operator|(L, R)

wobei LR das Ergebnis der üblichen arithmetischen Konvertierungen von L und R ist.

#include <bitset>
#include <cstdint>
#include <iomanip>
#include <iostream>
 
int main()
{
    std::uint16_t mask = 0x00f0;
    std::uint32_t x0 = 0x12345678;
    std::uint32_t x1 = x0 | mask;
    std::uint32_t x2 = x0 & ~mask;
    std::uint32_t x3 = x0 & mask;
    std::uint32_t x4 = x0 ^ mask;
    std::uint32_t x5 = ~x0;
    using bin16 = std::bitset<16>;
    using bin32 = std::bitset<32>;
    std::cout << std::hex << std::showbase
              << "Mask: " << mask << std::setw(49) << bin16(mask) << "\n"
                 "Value: " << x0 << std::setw(42) << bin32(x0) << "\n"
                 "Setting bits: " << x1 << std::setw(35) << bin32(x1) << "\n"
                 "Clearing bits: " << x2 << std::setw(34) << bin32(x2) << "\n"
                 "Selecting bits: " << x3 << std::setw(39) << bin32(x3) << "\n"
                 "XOR-ing bits: " << x4 << std::setw(35) << bin32(x4) << "\n"
                 "Inverting bits: " << x5 << std::setw(33) << bin32(x5) << '\n';
}

Ausgabe

Mask: 0xf0                                 0000000011110000
Value: 0x12345678          00010010001101000101011001111000
Setting bits: 0x123456f8   00010010001101000101011011111000
Clearing bits: 0x12345608  00010010001101000101011000001000
Selecting bits: 0x70       00000000000000000000000001110000
XOR-ing bits: 0x12345688   00010010001101000101011010001000
Inverting bits: 0xedcba987 11101101110010111010100110000111

[edit] Bitweise Shift-Operatoren

Die Ausdrücke der bitweisen Shift-Operatoren haben die Form:

lhs << rhs (1)
lhs >> rhs (2)
1) Bitweise Linksverschiebung.
2) Bitweise Rechtsverschiebung.

Bitweise Shift-Operatoren haben eine höhere Präzedenz als bitweise logische Operatoren, aber eine geringere Präzedenz als additive und multiplikative Operatoren. Diese Operatoren assoziieren von links nach rechts.

a >> b * c;  // equivalent to a >> (b * c),  NOT (a >> b) * c
d << e & f;  // equivalent to (d << e) & f,  NOT d << (e & f)
 
g << h >> i; // equivalent to (g << h) >> i, NOT g << (h >> i)

[edit] Eingebaute bitweise Shift-Operatoren

Für die eingebauten bitweisen Shift-Operatoren müssen beide Operanden prvalues vom ganzzahligen oder nicht-aufgezählten Enumerationstyp sein. Ganzzahlige Promotions werden für beide Operanden durchgeführt.

In der weiteren Beschreibung in diesem Abschnitt beziehen sich "Operand(en)", a, b, lhs und rhs auf die konvertierten oder beförderten Operanden.

Wenn der Wert von rhs negativ ist oder kleiner als die Anzahl der Bits in lhs ist, ist das Verhalten undefiniert.

Für vorzeichenlose a ist der Wert von a << b der Wert von a * 2b
, reduziert modulo 2N
, wobei N die Anzahl der Bits im Rückgabetyp ist (d. h., es wird eine bitweise Linksverschiebung durchgeführt und die Bits, die aus dem Zieltyp herausgeschoben werden, werden verworfen).

Für vorzeichenbehaftete und nicht-negative a gilt: Wenn a * 2b
im vorzeichenlosen Äquivalent des Rückgabetyps darstellbar ist, dann ist dieser Wert, konvertiert in vorzeichenbehaftet, der Wert von a << b (dies erlaubt es, INT_MIN als 1 << 31 zu erzeugen); andernfalls ist das Verhalten undefiniert.

Für negative a ist das Verhalten von a << b undefiniert.

Für vorzeichenlose a sowie für vorzeichenbehaftete und nicht-negative a ist der Wert von a >> b der ganzzahlige Teil von a/2b
.

Für negative a ist der Wert von a >> b implementierungsabhängig (in den meisten Implementierungen wird eine arithmetische Rechtsverschiebung durchgeführt, sodass das Ergebnis negativ bleibt).

(bis C++20)

Der Wert von a << b ist der eindeutige Wert, der kongruent zu a * 2b
modulo 2N
ist, wobei N die Anzahl der Bits im Rückgabetyp ist (d. h., es wird eine bitweise Linksverschiebung durchgeführt und die Bits, die aus dem Zieltyp herausgeschoben werden, werden verworfen).

Der Wert von a >> b ist a/2b
, gerundet in Richtung negativer Unendlichkeit (mit anderen Worten, eine Rechtsverschiebung bei vorzeichenbehaftetem a ist eine arithmetische Rechtsverschiebung).

(seit C++20)

Der Typ des Ergebnisses ist der Typ von lhs.

[edit] Überladungen

Bei der Überladungsauflösung für benutzerdefinierte Operatoren nehmen für jedes Paar von beförderten ganzzahligen Typen L und R die folgenden Funktionssignaturen an der Überladungsauflösung teil:

L operator<<(L, R)
L operator>>(L, R)
#include <iostream>
 
enum { ONE = 1, TWO = 2 };
 
int main()
{
    std::cout << std::hex << std::showbase;
    char c = 0x10;
    unsigned long long ull = 0x123;
    std::cout << "0x123 << 1 = " << (ull << 1) << "\n"
                 "0x123 << 63 = " << (ull << 63) << "\n" // overflow in unsigned
                 "0x10 << 10 = " << (c << 10) << '\n';   // char is promoted to int
    long long ll = -1000;
    std::cout << std::dec << "-1000 >> 1 = " << (ll >> ONE) << '\n';
}

Ausgabe

0x123 << 1 = 0x246
0x123 << 63 = 0x8000000000000000
0x10 << 10 = 0x4000
-1000 >> 1 = -500

[edit] Standardbibliothek

Arithmetische Operatoren sind für viele Standardbibliotheks-Typen überladen.

[edit] Unäre arithmetische Operatoren

implementiert unäres + und unäres -
(public member function of std::chrono::duration<Rep,Period>) [edit]
wendet unäre Operatoren auf komplexe Zahlen an
(function template) [edit]
wendet einen unären arithmetischen Operator auf jedes Element des Valarrays an
(public member function of std::valarray<T>) [edit]

[edit] Additive Operatoren

führt Additions- und Subtraktionsoperationen mit einem Zeitpunkt durch
(Funktionstemplate) [edit]
implementiert arithmetische Operationen mit Dauern als Argumente
(Funktionstemplate) [edit]
addiert oder subtrahiert einen year_month_day und eine Anzahl von Jahren oder Monaten
(Funktion) [bearbeiten]
verknüpft zwei Strings, einen String und ein char, oder einen String und string_view
(function template) [edit]
erhöht oder verringert den Iterator
(public member function of std::reverse_iterator<Iter>)
erhöht oder verringert den Iterator
(public member function of std::move_iterator<Iter>)
führt arithmetische Operationen mit komplexen Zahlen auf zwei komplexen Werten oder einer komplexen Zahl und einem Skalar durch
(function template) [edit]
wendet binäre Operatoren auf jedes Element zweier Valarrays oder eines Valarrays und eines Werts an
(function template) [edit]

[edit] Multiplikative Operatoren

implementiert arithmetische Operationen mit Dauern als Argumente
(Funktionstemplate) [edit]
führt arithmetische Operationen mit komplexen Zahlen auf zwei komplexen Werten oder einer komplexen Zahl und einem Skalar durch
(function template) [edit]
wendet binäre Operatoren auf jedes Element zweier Valarrays oder eines Valarrays und eines Werts an
(function template) [edit]

[edit] Bitweise logische Operatoren

führt binäre AND-, OR-, XOR- und NOT-Operationen durch
(public member function of std::bitset<N>) [edit]
führt binäre Logikoperationen auf Bitsets durch
(function template) [edit]
wendet einen unären arithmetischen Operator auf jedes Element des Valarrays an
(public member function of std::valarray<T>)
wendet binäre Operatoren auf jedes Element zweier Valarrays oder eines Valarrays und eines Werts an
(function template)

[edit] Bitweise Shift-Operatoren

wendet binäre Operatoren auf jedes Element zweier Valarrays oder eines Valarrays und eines Werts an
(function template)
führt binäre Links- und Rechtsschiebeoperationen durch
(public member function of std::bitset<N>)

[edit] Stream-Einfüge-/Extraktionsoperatoren

In der gesamten Standardbibliothek sind bitweise Shift-Operatoren häufig mit I/O-Streams (std::ios_base& oder einer davon abgeleiteten Klasse) sowohl als linker Operand als auch als Rückgabetyp überladen. Solche Operatoren werden als *Stream-Einfüge*- und *Stream-Extraktions*-Operatoren bezeichnet.

extrahiert formatierte Daten
(public member function of std::basic_istream<CharT,Traits>) [edit]
extrahiert Zeichen und Zeichen-Arrays
(function template) [bearbeiten]
fügt formatierte Daten ein
(public member function of std::basic_ostream<CharT,Traits>) [bearbeiten]
fügt Zeichendaten ein oder fügt in einen rvalue-Stream ein
(function template) [bearbeiten]
serialisiert und deserialisiert eine komplexe Zahl
(function template) [edit]
führt Stream-Ein- und -Ausgabe von Bitsets durch
(function template) [edit]
führt Stream-Ein- und -Ausgabe auf Strings durch
(function template) [edit]
führt Stream-Ein- und -Ausgabe auf Pseudo-Zufallszahlengeneratoren durch
(function template) [edit]
führt Stream-Ein- und -Ausgabe auf Pseudo-Zufallszahlendistributionen durch
(function template) [edit]

[edit] Defect Reports

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
CWG 614 C++98 der algebraische Quotient der ganzzahligen Division war
in implementierungsdefinierter Richtung gerundet
der algebraische Quotient der ganzzahligen
Division wird auf Null trunkiert
(der gebrochene Teil wird verworfen)
CWG 1450 C++98 das Ergebnis von a / b war undefiniert, wenn
es im Ergebnistyp nicht darstellbar ist
das Verhalten von sowohl a / b als auch
a % b ist in diesem Fall undefiniert
CWG 1457 C++98 das Verhalten des Verschiebens des linkensten 1-Bits eines
positiven vorzeichenbehafteten Werts in das Vorzeichenbit war undefiniert
wurde wohlformuliert
CWG 1504 C++98 ein Zeiger auf ein Basisklassen-Subobjekt eines Array-
Elements konnte in der Zeigerarithmetik verwendet werden
Das Verhalten ist
in diesem Fall nicht definiert.
CWG 1515 C++98 nur vorzeichenlose ganze Zahlen, die unsigned deklarierten
sollten die Gesetze der Arithmetik modulo 2n
befolgen
gilt für alle vorzeichenlosen ganzen Zahlen
CWG 1642 C++98 arithmetische Operatoren erlauben, dass ihre Operanden lvalues sind einige Operanden müssen rvalues sein
CWG 1865 C++98 die Auflösung von CWG-Problem 1504 machte die Verhaltensweisen
der Zeigerarithmetik, die Zeiger auf Array-Elemente betrifft,
undefiniert, wenn der referenzierte Typ und der Array-Elementtyp
unterschiedliche cv-Qualifikationen auf nicht-oberster Ebene haben
wurde wohlformuliert
CWG 1971 C++98 es war unklar, ob die Regel, die die
Mehrdeutigkeit von ~ auflöst, auf Fälle wie ~X(0) zutrifft
die Regel gilt für solche Fälle
CWG 2419 C++98 ein Zeiger auf ein Nicht-Array-Objekt wurde nur als ein
Zeiger auf das erste Element eines Arrays der Größe 1
in der Zeigerarithmetik behandelt, wenn der Zeiger durch & erhalten wurde
gilt für alle Zeiger
auf Nicht-Array-Objekte
CWG 2626 C++98 das Ergebnis des eingebauten operator~ war einfach
'Einerkomplement' ohne korrekte Definition
das Ergebnis wird in Begriffen
der Basis-2-Darstellung formuliert
CWG 2724 C++20 die Rundungsrichtung der arithmetischen Rechtsverschiebung war unklar wurde klargestellt
CWG 2853 C++98 ein Zeiger über das Ende eines Objekts konnte
nicht mit einer ganzen Zahl addiert oder subtrahiert werden
es kann

[edit] Siehe auch

Operatorrangfolge

Operatorüberladung

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
a->b
a.b
a->*b
a.*b

Funktionsaufruf

a(...)
Komma

a, b
Ternär

a ? b : c
Spezielle Operatoren

static_cast konvertiert einen Typ in einen anderen verwandten Typ
dynamic_cast konvertiert innerhalb von Vererbungshierarchien
const_cast fügt cv-Qualifizierer hinzu oder entfernt sie
reinterpret_cast konvertiert einen Typ in einen nicht verwandten Typ
C-Stil Cast konvertiert einen Typ in einen anderen durch eine Mischung aus static_cast, const_cast und reinterpret_cast
new erstellt Objekte mit dynamischer Speicherverwaltung
delete zerstört zuvor mit new-Ausdruck erstellte Objekte und gibt den zugewiesenen Speicherbereich frei
sizeof fragt die Größe eines Typs ab
sizeof... fragt die Größe eines packs ab (seit C++11)
typeid fragt die Typinformationen eines Typs ab
noexcept prüft, ob ein Ausdruck eine Ausnahme auslösen kann (seit C++11)
alignof fragt die Ausrichtungsvoraussetzungen eines Typs ab (seit C++11)

C-Dokumentation für Arithmetische Operatoren