Arithmetische Operatoren

Sprache C++

Allgemeine Themen
Flusskontrolle
Bedingte Ausführungsanweisungen

if

Iterationsanweisungen (Schleifen)

for

Bereich-for (C++11)

Sprunganweisungen

continuebreak

gotoreturn
Funktionen
Funktionsdeklaration
Lambda-Funktionsdeklaration
inline Spezifizierer
Ausnahmespezifikationen (bis C++20)
noexcept Spezifikation (C++11)
Ausnahmen
Namensräume
Typen
Bezeichner

decltype (C++11)

auto (C++11)

alignas (C++11)

const/volatile

constexpr (C++11)

Spezifizierer der Speicherdauer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolean – Ganzzahl – Fließkomma
Zeichen – Zeichenkette – nullptr (C++11)
Benutzer-definiert (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef Deklaration
Typ-Alias-Deklaration (C++11)
Casts
Implizite Konvertierungen – Explizite Konvertierungen
static_castdynamic_cast
const_castreinterpret_cast
Speicherzuweisung
Klassen
Klassen-.spezifische Funktionseigenschaften

Virtuelle Funktion

override specifier (C++11)

final specifier (C++11)

explicit (C++11)

static

Spezielle Mitgliedsfunktionen

Zuweisung kopieren

Zuweisung verschieben (C++11)

Destruktor

Vorlagen

Vorlagenspezialisierung

Parameterpakete (C++11)

Verschiedenes

Ausdrücke

Allgemeine

Wertkategorien (lvalue, rvalue, xvalue)

Reihenfolge der Auswertung (Sequenzpunkte)

Konstante Ausdrücke

Unbewertete Ausdrücke

Primäre Ausdrücke

Lambda-Ausdruck(C++11)

Literale

Ganzzahlige Literale

Gleitkomma-Punkt-Literale

Boolesche Literale

Zeichenliterale einschließlich Escape-Sequenzen

String-Literale

Null-Pointer-Literale (C++11)

Benutzerdefinierte Literale (C++11)

Operatoren

Zuweisungsoperatoren: a=b, a+=b, a-=b, a*=b, a/=b, a%=b, a&=b, a|=b, a^=b, a<<=b, a>>=b

Inkrement und Dekrement: ++a, --a, a++, a--

Arithmetische Operatoren:+a, -a, a+b, a-b, a*b, a/b, a%b, ~a, a&b, a|b, a^b, a<<b, a>>b

Logische Operatoren: a||b, a&&b, !a

Vergleichsoperatoren: a==b, a!=b, a<b, a>b, a<=b, a>=b, a<=>b(C++20)

Mitgliederzugriffsoperatoren: a, *a, &a, a->b, a.b, a->*b, a.*b

Andere Operatoren: a(...), a,b, a?b:c

new-Ausdruck

delete-Ausdruck

throw-Ausdruck

alignof

sizeof

sizeof…(C++11)

typeid

noexcept(C++11)

Fold expression(C++17)

Alternative Darstellungen von Operatoren

Precedence and associativity

Operator overloading

Standardvergleiche (C++20)

Konvertierungen

Implizite Konvertierungen

const_cast

static_cast

reinterpret_cast

dynamic_cast

Explizite Konvertierungen (T)a, T(a)

Benutzerdefinierte Konvertierung

Gibt das Ergebnis einer bestimmten arithmetischen Operation zurück.

Name des Operators Syntax Überladbar Beispiele für Prototypen (für Klasse T)
Innerhalb der Klassendefinition Außerhalb der Klassendefinition
unäres Plus +a Ja T T::operator+() const; T operator+(const T &a);
unäres Minus -a Ja T T::operator-() const; T operator-(const T &a);
Addition a + b Ja T T::operator+(const T2 &b) const; T operator+(const T &a, const T2 &b);
Subtraktion a - b Ja T T::operator-(const T2 &b) const; T operator-(const T &a, const T2 &b);
Multiplikation a * b Ja T T::operator*(const T2 &b) const; T operator*(const T &a, const T2 &b);
division a / b Ja T T::operator/(const T2 &b) const; T operator/(const T &a, const T2 &b);
modulo a % b Ja T T::operator%(const T2 &b) const; T operator%(const T &a, const T2 &b);
bitweise NOT ~a Ja T T::operator~() const; T operator~(const T &a);
bitweise UND a & b Ja T T::operator&(const T2 &b) const; T operator&(const T &a, const T2 &b);
bitweise OR a | b Ja T T::operator|(const T2 &b) const; T operator|(const T &a, const T2 &b);
bitwise XOR a ^ b Ja T T::operator^(const T2 &b) const; T operator^(const T &a, const T2 &b);
bitweise Linksverschiebung a << b Ja T T::operator<<(const T2 &b) const; T operator<<(const T &a, const T2 &b);
bitweise Rechtsverschiebung a >> b Ja T T::operator>>(const T2 &b) const; T operator>>(const T &a, const T2 &b);
Hinweise

  • Alle eingebauten Operatoren geben Werte zurück, und die meisten benutzerdefinierten Überladungen geben ebenfalls Werte zurück, so dass die benutzerdefinierten Operatoren auf dieselbe Weise wie die eingebauten verwendet werden können. In einer benutzerdefinierten Operatorüberladung kann jedoch jeder Typ als Rückgabetyp verwendet werden (einschließlich void). Insbesondere die Stream-Insertion- und Stream-Extraction-Überladungen von operator<< und operator>> geben T& zurück.
  • T2 kann jeder Typ sein, einschließlich T

  • 1 Erläuterung
    • 1.1 Konvertierungen
    • 1.2 Überläufe
    • 1.3 Fließkommaumgebung
    • 1.4 Fließkommakontraktion
    • 1.5 Unäre arithmetische Operatoren
    • 1.6 Additive Operatoren
    • 1.7 Multiplikative Operatoren
    • 1.8 Bitweise logische Operatoren
    • 1.9 Bitweise Schiebeoperatoren
  • 2 Standardbibliothek
    • 2.1 Unäre arithmetische Operatoren
    • 2.2 Additive Operatoren
    • 2.3 Multiplikative Operatoren
    • 2.4 Bitweise logische Operatoren
    • 2.5 Bitweise Schiebeoperatoren
    • 2.6 Stream Insertion/Extraction Operatoren
  • 3 Fehlerberichte
  • 4 Siehe auch

Erläuterung

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

Konvertierungen

Wenn der an einen arithmetischen Operator übergebene Operand vom Typ Integral oder unscoped enumeration ist, dann wird der Operand vor jeder anderen Aktion (aber nach der Konvertierung von lWert zu rWert, falls zutreffend) einer integralen Promotion unterzogen. Wenn ein Operand vom Typ Array oder Funktion ist, werden Array-zu-Zeiger- und Funktions-zu-Zeiger-Konvertierungen durchgeführt.

Für die binären Operatoren (mit Ausnahme von Verschiebungen) werden, wenn die beförderten Operanden unterschiedliche Typen haben, zusätzliche implizite Konvertierungen durchgeführt, die als übliche arithmetische Konvertierungen bekannt sind, mit dem Ziel, den gemeinsamen Typ zu erzeugen (auch zugänglich über die std::common_type type trait). Wenn vor einer integralen Promotion ein Operand vom Aufzählungstyp und der andere Operand von einem Fließkommatyp oder einem anderen Aufzählungstyp ist, ist dieses Verhalten veraltet. (seit C++20)

  • Wenn einer der beiden Operanden einen Aufzählungstyp hat, wird keine Konvertierung durchgeführt: der andere Operand und der Rückgabetyp müssen denselben Typ haben
  • Andernfalls, wenn einer der beiden Operanden long double ist, wird der andere Operand in long double umgewandelt
  • Andernfalls, wenn einer der beiden Operanden double ist, wird der andere Operand in double umgewandelt
  • Andernfalls, wenn einer der beiden Operanden float ist, wird der andere Operand in float umgewandelt
  • Andernfalls hat der Operand den Typ integer (weil bool, char, char8_t, char16_t, char32_t, wchar_t und unscoped enumeration an dieser Stelle befördert wurden), und es werden Integralumwandlungen durchgeführt, um den gemeinsamen Typ wie folgt zu erzeugen:
  • Wenn beide Operanden vorzeichenbehaftet oder vorzeichenlos sind, wird der Operand mit dem niedrigeren Konvertierungsrang in den Operanden mit dem höheren ganzzahligen Konvertierungsrang konvertiert
  • Andernfalls, wenn der Konvertierungsrang des vorzeichenlosen Operanden größer oder gleich dem Konvertierungsrang des vorzeichenbehafteten Operanden ist, wird der vorzeichenbehaftete Operand in den Typ des vorzeichenlosen Operanden konvertiert.
  • Andernfalls, wenn der Typ des vorzeichenbehafteten Operanden alle Werte des vorzeichenlosen Operanden darstellen kann, wird der vorzeichenlose Operand in den Typ des vorzeichenbehafteten Operanden konvertiert
  • Andernfalls werden beide Operanden in das vorzeichenlose Gegenstück des Typs des vorzeichenbehafteten Operanden konvertiert.

Der obige Konvertierungsrang steigt in der Reihenfolge bool, signed char, short, int, long, long long. Der Rang eines beliebigen vorzeichenlosen Typs ist gleich dem Rang des entsprechenden vorzeichenbehafteten Typs. Der Rang von char ist gleich dem Rang von signed char und unsigned char. Die Ränge von char8_t, char16_t, char32_t und wchar_t sind gleich den Rängen der zugrundeliegenden Typen.

Überläufe

Die Arithmetik von Ganzzahlen ohne Vorzeichen wird immer modulo 2n
durchgeführt, wobei n die Anzahl der Bits der jeweiligen Ganzzahl ist. Z.B. für unsigned int ergibt die Addition von 1 zu UINT_MAX 0, und die Subtraktion von 1 von 0 ergibt UINT_MAX.

Wenn eine arithmetische Operation für Ganzzahlen mit Vorzeichen überläuft (das Ergebnis passt nicht in den Ergebnistyp), ist das Verhalten undefiniert, – die möglichen Erscheinungsformen einer solchen Operation sind:

  • es wird nach den Regeln der Darstellung (typischerweise 2er-Komplement) umbrochen,
  • es wird gefangen – auf einigen Plattformen oder aufgrund von Compiler-Optionen (z.z. B. -ftrapv in GCC und Clang),
  • es sättigt auf minimalen oder maximalen Wert (auf vielen DSPs),
  • es wird vom Compiler komplett herausoptimiert.

Fließkomma-Umgebung

Wenn #pragma STDC FENV_ACCESS unterstützt wird und auf ON gesetzt ist, gehorchen alle arithmetischen Fließkomma-Operatoren der aktuellen Fließkomma-Rundungsrichtung und melden Fließkomma-Arithmetikfehler wie in math_errhandling angegeben, es sei denn, sie sind Teil eines statischen Initialisierers (in diesem Fall werden keine Fließkomma-Ausnahmen ausgelöst und der Rundungsmodus ist der nächstliegende)

Fließkomma-Kontraktion

Wenn #pragma STDC FP_CONTRACT unterstützt wird und auf OFF gesetzt ist, können alle Gleitkomma-Arithmetiken so ausgeführt werden, als hätten die Zwischenergebnisse einen unendlichen Bereich und eine unendliche Genauigkeit, d. h. Optimierungen, die Rundungsfehler und Gleitkomma-Ausnahmen ausschließen, sind zulässig. Zum Beispiel erlaubt C++ die Implementierung von (x*y) + z mit einer einzigen verschmolzenen Multiplikations-Additions-CPU-Anweisung 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 einen anderen Bereich und eine andere Genauigkeit haben, als der Typ angibt, siehe FLT_EVAL_METHOD

Formalerweise gibt der C++-Standard keine Garantie für die Genauigkeit von Gleitkommaoperationen.

Unäre arithmetische Operatoren

Die Ausdrücke der unären arithmetischen Operatoren haben die Form

+ Ausdruck (1)
- Ausdruck (2)
1) unär plus (Förderung).
Für den eingebauten Operator muss der Ausdruck vom Typ Arithmetik, unscoped enumeration oder Pointer sein. Die integrale Promotion wird für den Operanden durchgeführt, wenn er vom Typ Integral oder unscoped enumeration ist, und bestimmt den Typ des Ergebnisses.
2) unary minus (Negation).
Für den eingebauten Operator muss der Ausdruck vom Typ arithmetisch oder unscoped enumeration sein. Die integrale Promotion wird am Operanden durchgeführt und bestimmt den Typ des Ergebnisses.

Der eingebaute unäre Plus-Operator gibt den Wert seines Operanden zurück. Die einzige Situation, in der er kein No-op ist, ist, wenn der Operand einen Integraltyp oder einen nicht skopierten Aufzählungstyp hat, der durch integrale Promotion geändert wird, z.B. wenn er char in int konvertiert oder wenn der Operand einer lvalue-to-rvalue-, array-to-pointer- oder function-to-pointer-Konvertierung unterliegt.

Der eingebaute unäre Minus-Operator berechnet das Negativ seines promoteten Operanden. Für vorzeichenlos a ist der Wert von -a 2b
-a, wobei b die Anzahl der Bits nach der Promotion ist.

Bei der Überlastauflösung gegen benutzerdefinierte Operatoren nehmen für jeden promoteten arithmetischen Typ A und für jeden Typ T die folgenden Funktionssignaturen an der Überlastauflösung teil:

A operator+(A)

T* operator+(T*)

A operator-(A)

Diesen Code ausführen
#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; std::cout << "size of array: " << sizeof a << '\n' << "size of pointer: " << sizeof +a << '\n';}

Ausgabe:

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

Additive Operatoren

Die binären additiven arithmetischen Operatorausdrücke haben die Form

lhs + rhs (1)
lhs - rhs (2)
1) Addition
Für den eingebauten-in-Operator, müssen lhs und rhs eine der folgenden Angaben sein:

  • beide haben den Typ arithmetisch oder unscoped enumeration. In diesem Fall werden die üblichen arithmetischen Konvertierungen an beiden Operanden durchgeführt und bestimmen den Typ des Ergebnisses.
  • Einer ist ein Zeiger auf einen vollständig definierten Objekttyp, der andere hat den Typ Integral oder unscoped enumeration. In diesem Fall hat der Ergebnistyp den Typ des Zeigers.
2) Subtraktion
Für den eingebauten Operator müssen lhs und rhs einer der folgenden sein:

  • beide haben einen arithmetischen oder nicht skopierten Aufzählungstyp. In diesem Fall werden die üblichen arithmetischen Konvertierungen an beiden Operanden durchgeführt und bestimmen den Typ des Ergebnisses.
  • lhs ist ein Zeiger auf einen vollständig definierten Objekttyp, rhs hat den Typ Integral oder unscoped enumeration. In diesem Fall hat der Ergebnistyp den Typ des Zeigers.
  • beides sind Zeiger auf die gleichen vollständig definierten Objekttypen, ohne Berücksichtigung von cv-Qualifiern. In diesem Fall ist der Ergebnistyp std::ptrdiff_t.

Bei Operanden vom Typ Arithmetik oder Aufzählung ist das Ergebnis des binären Plus-Operators die Summe der Operanden (nach den üblichen arithmetischen Umrechnungen) und das Ergebnis des binären Minus-Operators ist das Ergebnis der Subtraktion des zweiten Operanden vom ersten (nach den üblichen arithmetischen Umrechnungen), außer wenn der Typ die IEEE-Gleitkomma-Arithmetik unterstützt (siehe std::numeric_limits::is_iec559),

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

Wenn einer der Operanden ein Zeiger ist, gelten die folgenden Regeln:

  • Ein Zeiger auf ein Nicht-Array-Objekt wird wie ein Zeiger auf das erste Element eines Arrays der Größe 1 behandelt.
  • Wenn der Zeiger P auf das i-te Element eines Arrays zeigt, dann sind die Ausdrücke P+n, n+P und P-n Zeiger des gleichen Typs, die auf das i+n-te, i+n-te bzw. i-n-te Element desselben Arrays zeigen. Das Ergebnis der Zeigeraddition kann auch ein Zeiger sein, der bis zum Ende reicht (d. h. Zeiger P, so dass der Ausdruck P-1 auf das letzte Element des Arrays zeigt). Alle anderen Situationen (d.h. Versuche, einen Zeiger zu erzeugen, der nicht auf ein Element desselben Arrays oder eines hinter dem Ende zeigt) rufen ein undefiniertes Verhalten hervor.
  • Wenn der Zeiger P auf das i-te Element eines Arrays zeigt und der Zeiger Q auf das j-te Element desselben Arrays zeigt, hat der Ausdruck P-Q den Wert i-j, wenn der Wert in std::ptrdiff_t passt. Beide Operanden müssen auf die Elemente desselben Arrays (oder eines hinter dem Ende) zeigen, sonst ist das Verhalten undefiniert. Wenn das Ergebnis nicht in std::ptrdiff_t passt, ist das Verhalten undefiniert.
  • In jedem Fall ist das Verhalten der Zeigerarithmetik undefiniert, wenn der Typ, auf den gezeigt wird, sich vom Typ des Arrayelements unterscheidet, ungeachtet der cv-Qualifikationen, auf jeder Ebene, wenn die Elemente selbst Zeiger sind. Insbesondere ist die Zeigerarithmetik mit einem Zeiger auf eine Basis, die auf ein Element eines Arrays von abgeleiteten Objekten zeigt, undefiniert.
  • Wenn der Wert 0 von einem Zeiger addiert oder subtrahiert wird, ist das Ergebnis der Zeiger, unverändert. Wenn zwei Zeiger auf dasselbe Objekt zeigen oder beide über das Ende desselben Arrays hinausgehen oder beide Null-Zeiger sind, dann ist das Ergebnis der Subtraktion gleich (std::ptrdiff_t)0.

Diese Zeiger-Arithmetik-Operatoren erlauben es Zeigern, die LegacyRandomAccessIterator-Anforderungen zu erfüllen.

Bei der Überladungsauflösung gegenüber benutzerdefinierten Operatoren nehmen für jedes Paar von promoteten 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 Umrechnungen auf L und R

Führen Sie diesen Code aus
#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 = {'a', 'b', 'c', 'd'}; char* p = &a; std::cout << "Pointer addition examples: " << *p << *(p + 2) << *(2 + p) << *(p - 1) << '\n'; char* p2 = &a; 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.12Pointer addition examples: bddaPointer difference: 3

Multiplikative Operatoren

Die binären multiplikativen arithmetischen Operatorausdrücke haben die Form

lhs * rhs (1)
lhs / rhs (2)
lhs % rhs (3)
1) Multiplikation
Für den eingebauten-in-Operator, lhs und rhs müssen beide den Typ arithmetisch oder unscoped enumeration haben.
2) Division
Für den eingebauten Operator müssen sowohl lhs als auch rhs vom Typ arithmetisch oder unscoped enumeration sein.
3) Rest
Für den eingebauten Operator müssen lhs und rhs beide vom Typ Integral oder unscoped enumeration sein

Für alle drei Operatoren werden die üblichen arithmetischen Umwandlungen an beiden Operanden durchgeführt und bestimmen den Typ des Ergebnisses.

Der binäre Operator * führt eine Multiplikation seiner Operanden durch (nach den üblichen arithmetischen Umwandlungen), außer bei der Fließkommamultiplikation,

  • Die Multiplikation von NaN mit einer beliebigen Zahl ergibt NaN
  • Die Multiplikation von Unendlich mit Null ergibt NaN und FE_INVALID wird ausgelöst

Der Binäroperator / dividiert den ersten Operanden durch den zweiten (nach den üblichen arithmetischen Umrechnungen).

Bei ganzzahligen Operanden ergibt er den algebraischen Quotienten.

Der Quotient wird in implementierungsdefinierter Richtung gerundet.

(bis C++11)

Der Quotient wird gegen Null abgeschnitten (Nachkommastelle wird verworfen).

(seit C++11)

Wenn der zweite Operand Null ist, ist das Verhalten undefiniert, außer wenn eine Fließkommadivision stattfindet und der Typ IEEE-Fließkommaarithmetik unterstützt (siehe std::numeric_limits::is_iec559), dann:

  • wenn ein Operand NaN ist, ist das Ergebnis NaN
  • Division einer Zahl ungleich Null durch ±0.0 ergibt die korrekt vorzeichenbehaftete Unendlichkeit und FE_DIVBYZERO wird ausgelöst
  • Dividieren von 0,0 durch 0,0 ergibt NaN und FE_INVALID wird ausgelöst

Der Binäroperator % liefert den Rest der ganzzahligen Division des ersten Operanden durch den zweiten (nach den üblichen arithmetischen Umwandlungen; beachten Sie, dass die Operandentypen ganzzahlig sein müssen). Wenn der Quotient a/b im Ergebnistyp darstellbar ist, ist (a/b)*b + a%b == a. Wenn der zweite Operand Null ist, ist das Verhalten undefiniert. Wenn der Quotient a/b im Ergebnistyp nicht darstellbar ist, ist das Verhalten von a/b und a%b undefiniert (d.h. INT_MIN%-1 ist auf 2er-Komplement-Systemen undefiniert)

Hinweis: Bis C++11 war das Vorzeichen des Rests implementierungsabhängig, wenn einer oder beide Operanden des Binäroperators % negativ waren, da es von der Rundungsrichtung der Ganzzahldivision abhing. Die Funktion std::div lieferte in diesem Fall ein wohldefiniertes Verhalten.

Hinweis: Für den Fließkomma-Rest siehe std::remainder und std::fmod.

Bei der Überladungsauflösung gegen benutzerdefinierte Operatoren nehmen für jedes Paar von promoteten arithmetischen Typen LA und RA und für jedes Paar von promoteten integralen 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 üblichen arithmetischen Umrechnungen auf Lx und Rx

Führ diesen Code aus
#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 = -202 * (-10), where 2 is unsigned = 4294967276-10 / 2.12 = -4.71698-10 / 21 = 0-10 % 21 = -10

Bitweise logische Operatoren

Die bitweisen arithmetischen Operatorausdrücke 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
Für die eingebauteneingebauten Operatoren, lhs und rhs müssen beide vom Typ Integral oder unscoped enumeration sein. Die üblichen arithmetischen Umwandlungen werden an beiden Operanden durchgeführt und bestimmen den Typ des Ergebnisses.

Das Ergebnis von Operator~ ist der bitweise NICHT-Wert (Einerkomplement) des Arguments (nach Promotion). Das Ergebnis des Operators& ist der bitweise UND-Wert der Operanden (nach den üblichen arithmetischen Umrechnungen). Das Ergebnis von operator| ist der bitweise ODER-Wert der Operanden (nach den üblichen arithmetischen Umrechnungen). Das Ergebnis von Operator^ ist der bitweise XOR-Wert der Operanden (nach üblichen arithmetischen Konvertierungen)

Bei der Überladungsauflösung gegen benutzerdefinierte Operatoren nehmen für jedes Paar von promoteten Integraltypen 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 Umrechnungen auf L und R

Führen Sie diesen Code aus
#include <iostream>int main(){ std::cout << std::hex << std::showbase; uint16_t mask = 0x00f0; uint32_t a = 0x12345678; std::cout << "Value: " << a << " mask: " << mask << '\n' << "Setting bits: " << (a | mask) << '\n' << "Clearing bits: " << (a & ~mask) << '\n' << "Selecting bits: " << (a & mask) << '\n';}

Ausgabe:

Value: 0x12345678 mask: 0xf0Setting bits: 0x123456f8Clearing bits: 0x12345608Selecting bits: 0x70

Bitweise Schiebeoperatoren

Die bitweisen Schiebeoperator-Ausdrücke haben die Form

lhs << rhs (1)
lhs >> rhs (2)
1) Linksverschiebung von lhs um rhs-Bits
2) Rechtsverschiebung von lhs um rhs-Bits
Für die eingebauten-eingebauten Operatoren, lhs und rhs müssen beide den Typ Integral oder unscoped enumeration haben. Integrale Promotionen werden an beiden Operanden durchgeführt.

Der Rückgabetyp ist der Typ des linken Operanden nach integralen Promotionen.

Für unsigned 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, wenn ein * 2b
in der vorzeichenlosen Version des Rückgabetyps darstellbar ist, dann ist dieser Wert, konvertiert in vorzeichenbehaftet, der Wert von a << b (dies macht es legal, INT_MIN als 1<<31 zu erstellen); andernfalls ist das Verhalten undefiniert.

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

Für vorzeichenloses a und für vorzeichenbehaftetes und nicht-negatives a ist der Wert von a >> b der ganzzahlige Teil von a/2b
.

Für negatives a ist der Wert von a >> b implementierungsdefiniert (in den meisten Implementierungen wird damit eine arithmetische Rechtsverschiebung durchgeführt, so dass das Ergebnis negativ bleibt).

(bis C++20)

Der Wert von a << b ist der einzige 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
, abgerundet (mit anderen Worten, Rechtsverschiebung auf vorzeichenbehaftetem a ist arithmetische Rechtsverschiebung).

(seit C++20)

In jedem Fall ist das Verhalten undefiniert, wenn der Wert des rechten Operanden negativ ist oder größer oder gleich der Anzahl der Bits im beförderten linken Operanden ist.

Bei der Überladungsauflösung gegen benutzerdefinierte Operatoren nehmen für jedes Paar von promoteten Integraltypen L und R die folgenden Funktionssignaturen an der Überladungsauflösung teil:

L Operator<<(L, R)

L Operator>>(L, R)

Diesen Code ausführen
#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 = 0x2460x123 << 63 = 0x80000000000000000x10 << 10 = 0x4000-1000 >> 1 = -500

Standardbibliothek

Arithmetische Operatoren sind für viele Typen der Standardbibliothek überladen.

Unäre arithmetische Operatoren

implementiert unäres + und unäres –
(public member function of std::chrono::duration<Rep,Period>)

wendet unäre Operatoren auf komplexe Zahlen an
(function template)

wendet einen unären arithmetischen Operator auf jedes Element des valarray an
(public member function of std::valarray<T>)

Additive Operatoren

führt Additions- und Subtraktionsoperationen mit einem Zeitpunkt durch
(Funktionsschablone)

implementiert arithmetische Operationen mit Dauern als Argumente
(Funktionsschablone)

addiert oder subtrahiert eine year_month_day und einige Anzahl von Jahren oder Monaten
(öffentliche Mitgliedsfunktion von std::chrono::year_month_day)

verkettet zwei Strings oder einen String und ein Char
(Funktionsschablone)

schiebt den Iterator vor oder zurück
(öffentliche Mitgliedsfunktion von std::reverse_iterator<Iter>)

verschiebt oder dekrementiert den Iterator
(öffentliche Mitgliedsfunktion von std::move_iterator<Iter>)

führt komplexe Zahlenarithmetik auf zwei komplexe Werte oder einen Komplexen und einen Skalar aus
(Funktionsvorlage)

wendet binäre Operatoren auf jedes Element von zwei Valarrays an, oder ein Valarray und einen Wert
(Funktionsvorlage)

Multiplikative Operatoren

implementiert arithmetische Operationen mit Dauern als Argumente
(Funktionsvorlage)

führt komplexe Zahlenarithmetik auf zwei komplexe Werte oder einen Komplexen und einen Skalar aus
(Funktionsvorlage)

wendet binäre Operatoren auf jedes Element von zwei Valarrays an, oder ein Valarray und einen Wert
(Funktionsschablone)

Bitweise Logikoperatoren

führt binäres AND, OR, XOR und NOT
(public member function of std::bitset<N>)

führt binäre logische Operationen auf Bitsets durch
(function template)

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 von zwei Valarrays an, or a valarray and a value
(function template)

Bitwise shift operators

wendet binäre Operatoren auf jedes Element von zwei valarrays an, oder ein Valarray und einen Wert
(Funktionsschablone)

führt binäre Verschiebung nach links und rechts durch
(öffentliche Mitgliedsfunktion von std::bitset<N>)

Stream-Einfüge-/Entnahmeoperatoren

In der gesamten Standardbibliothek werden bitweise Verschiebeoperatoren häufig mit I/O-Stream überladen (std::ios_base& oder eine der davon abgeleiteten Klassen) sowohl als linker Operand als auch als Rückgabetyp überladen. Solche Operatoren sind als Stream-Insertion- und Stream-Extraction-Operatoren bekannt:

extrahiert formatierte Daten
(public member function of std::basic_istream<CharT,Traits>)

extrahiert Zeichen und Zeichenarrays
(function template)

fügt formatierte Daten ein
(public member function of std::basic_ostream<CharT,Traits>)

fügt Zeichendaten ein
(function template)

serialisiert und deserialisiert eine komplexe Zahl
(Funktionsvorlage)

führt Stream-Eingabe und -Ausgabe von Bitsets durch
(Funktionsvorlage)

führt Stream-Eingabe und -Ausgabe von Strings durch
(Funktionsvorlage)

führt Stream-Eingabe und -Ausgabe von PseudoZufallszahlen-Engine
(Funktionsschablone)

führt Stream-Eingabe und -Ausgabe auf Pseudo-Zufallszahlenverteilung durch
(Funktionsschablone)

Mängelberichte

Die folgenden verhaltensändernden Mängelberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewandt.

DR Angewandt auf Verhalten wie veröffentlicht Korrektes Verhalten
CWG 1457 C++98 Das Verschieben des ganz linken 1 Bits eines positiven vorzeichenbehafteten Wertes in das Vorzeichenbit wurde UB gut gemachtdefiniert

Siehe auch

Operatorvorrang

Operatorüberladung

Gemeinsame Operatoren
Zuweisung Inkrement
Dekrement
Arithmetisch 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

a(…)
a, b
? :

Spezielle Operatoren

static_cast konvertiert einen Typ in einen anderen verwandten Typ
dynamic_cast konvertiert innerhalb von Vererbungshierarchien
const_cast fügt cv-Qualifikatoren hinzu oder entfernt sie
reinterpret_cast konvertiert einen Typ in einen nicht verwandten Typ
C-style cast konvertiert einen Typ in einen anderen durch eine Mischung von static_cast, const_cast und reinterpret_cast
new erzeugt Objekte mit dynamischer Speicherdauer
delete zerstört Objekte, die zuvor durch den new-Ausdruck erzeugt wurden und gibt den erhaltenen Speicherbereich frei
sizeof fragt die Größe eines Typs ab
sizeof… fragt die Größe eines Parameterpakets 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 Ausrichtungsanforderungen eines Typs ab (seit C++11)

C-Dokumentation für arithmetische Operatoren

Schreibe einen Kommentar