Namespaces
Variants

Arithmetic operators

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Gibt das Ergebnis der spezifischen arithmetischen Operation zurück.

Operatorname Syntax Prototypbeispiele (für class T )
Innerhalb der Klassendefinition Außerhalb der Klassendefinition
Unäres Plus + a T T :: operator + ( ) const ; T operator + ( const T & a ) ;
Unäres Minus - 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 NOT ~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 ) ;
Bitweise Linksverschiebung a << b T T :: operator << ( const T2 & b ) const ; T operator << ( const T & a, const T2 & b ) ;
Bitweise Rechtsverschiebung a >> b T T :: operator >> ( const T2 & b ) const ; T operator >> ( const T & a, const T2 & b ) ;
Hinweise
  • Alle Operatoren in dieser Tabelle sind überladbar .
  • Alle eingebauten Operatoren geben Werte zurück, und die meisten benutzerdefinierten Überladungen geben ebenfalls Werte zurück, damit die benutzerdefinierten Operatoren auf die gleiche Weise wie die eingebauten verwendet werden können. Allerdings kann bei einer benutzerdefinierten Operatorüberladung 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 einschließlich T sein.

Inhaltsverzeichnis

Allgemeine Erklärung

Alle eingebauten arithmetischen Operatoren berechnen das Ergebnis einer spezifischen arithmetischen Operation und geben ihr Ergebnis zurück. Die Argumente werden nicht modifiziert.

Konvertierungen

Wenn der an einen eingebauten arithmetischen Operator übergebene Operand ein integraler oder unbegrenzter Aufzählungstyp ist, dann durchläuft der Operand vor jeder anderen Aktion (aber nach der Lvalue-zu-Rvalue-Konvertierung, falls zutreffend) Integral Promotion . Wenn ein Operand Array- oder Funktionstyp hat, werden Array-zu-Zeiger - und Funktion-zu-Zeiger -Konvertierungen angewendet.

Für die binären Operatoren (außer Verschiebungen), wenn die höhergestuften Operanden unterschiedliche Typen haben, übliche arithmetische Konvertierungen werden angewendet.

Überläufe

Die Arithmetik vorzeichenloser Ganzzahlen wird stets modulo 2 n
durchgeführt, wobei n die Anzahl der Bits in der jeweiligen Ganzzahl ist. Zum Beispiel ergibt für unsigned int das Addieren von eins zu UINT_MAX den Wert 0 , und das Subtrahieren von eins von 0 ergibt UINT_MAX .

Wenn eine Operation mit vorzeichenbehafteten Ganzzahlen überläuft (das Ergebnis passt nicht in den Ergebnistyp), ist das Verhalten undefiniert — die möglichen Ausprägungen einer solchen Operation umfassen:

  • es umläuft gemäß den Regeln der Darstellung (typischerweise two's complement ),
  • es löst eine Trap aus — auf einigen Plattformen oder aufgrund von Compiler-Optionen (z.B. -ftrapv in GCC und Clang),
  • es sättigt zum Minimal- oder Maximalwert (auf vielen DSPs),
  • es wird vollständig optimized out by the compiler .

Gleitkomma-Umgebung

Wenn #pragma STDC FENV_ACCESS unterstützt wird und auf ON gesetzt ist, befolgen alle Gleitkomma-Operatoren die aktuelle Rundungsrichtung und melden Gleitkomma-Arithmetikfehler wie in math_errhandling spezifiziert, es sei denn, sie sind Teil eines statischen Initialisierers (in diesem Fall werden keine Gleitkomma-Ausnahmen ausgelöst und der Rundungsmodus ist "zu nächstem").

Gleitkomma-Kontraktion

Sofern nicht #pragma STDC FP_CONTRACT unterstützt wird und auf OFF gesetzt ist, darf alle Gleitkommaarithmetik so ausgeführt werden, als ob die Zwischenergebnisse unendlichen Wertebereich und unendliche Genauigkeit hätten, das heißt, Optimierungen, die Rundungsfehler und Gleitkomma-Ausnahmen auslassen, sind erlaubt. Beispielsweise erlaubt C++ die Implementierung von ( x * y ) + z mit einer einzelnen fused multiply-add CPU-Instruktion oder die Optimierung von a = x * x * x * x ; zu tmp = x * x ; a = tmp * tmp .

Unabhängig von der Vertragsgestaltung können Zwischenergebnisse der Gleitkommaarithmetik einen Bereich und eine Genauigkeit aufweisen, die von der durch ihren Typ angegebenen abweichen, siehe FLT_EVAL_METHOD .

Formal macht der C++-Standard keine Zusicherung bezüglich der Genauigkeit von Gleitkommaoperationen.

Unäre arithmetische Operatoren

Die unären arithmetischen Operatorausdrücke haben die Form

+ Ausdruck (1)
- Ausdruck (2)
1) Unärer Plus (Promotion).
2) Unäres Minus (Negation).

Unäre + und - Operatoren haben eine höhere Präzedenz als alle binären arithmetischen Operatoren, daher kann der Ausdruck keine obersten binären arithmetischen Operatoren enthalten. Diese Operatoren assoziieren von rechts nach links:

+a - b; // entspricht (+a) - b, NICHT +(a - b)
-c + d; // entspricht (-c) + d, NICHT -(c + d)
+-e; // entspricht +(-e), das unäre + ist ein No-Op, wenn "e" ein eingebauter Typ ist
     // da jede mögliche Höherstufung bereits während der Negation durchgeführt wird

Eingebaute unäre arithmetische Operatoren

1) Für den eingebauten unären Plus-Operator muss expression ein Prvalue arithmetischen Typs, eines unbegrenzten Aufzählungstyps oder eines Zeigertyps sein. Ganzzahlige Höherwertung wird auf expression durchgeführt, wenn sie ganzzahligen oder unbegrenzten Aufzählungstyp hat. Der Typ des Ergebnisses ist der (möglicherweise höherwertige) Typ von expression .
Das Ergebnis der eingebauten Promotion ist der Wert des Ausdrucks . Die eingebaute unäre Operation ist ein No-Op, wenn der Operand ein Prvalue eines promovierten integralen Typs oder eines Zeigertyps ist. Andernfalls wird der Typ oder die Wertkategorie des Operanden durch Integral Promotion oder Lvalue-zu-Rvalue-, Array-zu-Zeiger-, Funktion-zu-Zeiger- oder benutzerdefinierte Konvertierung geändert. Zum Beispiel wird char zu int konvertiert, und nicht-generisches captureless Lambda-Ausdruck wird in unären Plus-Ausdrücken zu Funktionszeiger konvertiert (seit C++11) .
2) Für den eingebauten unären Minus-Operator muss expression ein Prvalue eines arithmetischen Typs oder eines unbegrenzten Aufzählungstyps sein. Ganzzahlige Höherstufung wird auf expression durchgeführt. Der Typ des Ergebnisses ist der Typ des höhergestuften Typs von expression .
Das Ergebnis der eingebauten Negation ist das Negative des heraufgestuften expression . Für unsigned a ist der Wert von - a gleich 2 N
-a
, wobei N die Anzahl der Bits nach der Heraufstufung ist.
  • Mit anderen Worten, das Ergebnis ist das Zweierkomplement des Operanden (wobei Operand und Ergebnis als unsigned betrachtet werden).

Überladungen

Bei Überlagerungsauflösung für benutzerdefinierte Operatoren nehmen für jeden cv-unqualifizierten promoted arithmetischen Typ A und für jeden Typ T die folgenden Funktionssignaturen an der Überlagerungsauflö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

Additive Operatoren

Die additiven Operatorausdrücke haben die Form

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

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

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

Eingebaute additive Operatoren

Für eingebaute binäre Plus- und Minusoperatoren müssen sowohl lhs als auch rhs Prvalues sein, und eine der folgenden Bedingungen muss erfüllt sein:

  • Beide Operanden haben arithmetischen oder unbegrenzten Aufzählungstyp. In diesem Fall werden usual arithmetic conversions auf beide Operanden angewendet.
  • Genau ein Operand hat integralen oder unbegrenzten Aufzählungstyp. In diesem Fall wird integral promotion auf diesen Operanden angewendet.

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

1) Für eingebaute Addition muss eine der folgenden Bedingungen erfüllt sein:
  • Beide Operanden haben 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 ganzzahligen Typ. In diesem Fall wird der ganzzahlige Wert zum Zeiger addiert (siehe pointer arithmetic ).
2) Für eingebaute Subtraktion muss eine der folgenden Bedingungen erfüllt sein:
  • Beide Operanden haben arithmetischen Typ. In diesem Fall ist das Ergebnis die Differenz aus der Subtraktion von rhs von lhs .
  • lhs ist ein Zeiger auf einen vollständig definierten Objekttyp, und rhs hat ganzzahligen Typ. In diesem Fall wird der Ganzzahlwert 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.
  • Unendlich minus Unendlich ist NaN, und FE_INVALID wird ausgelöst.
  • Unendlich plus negativ Unendlich ist NaN, und FE_INVALID wird ausgelöst.

Zeigerarithmetik

Wenn ein Ausdruck J mit ganzzahligem Typ zu einem Ausdruck P mit Zeigertyp addiert oder von diesem subtrahiert wird, hat das Ergebnis den Typ von P .

  • Wenn P zu einem Null-Zeigerwert ausgewertet wird und J zu 0 ausgewertet wird, ist das Ergebnis ein Null-Zeigerwert.
  • Andernfalls, wenn P auf das i -te Element eines Array-Objekts x mit n Elementen zeigt, und der Wert von J als j gegeben ist, wird P wie folgt addiert oder subtrahiert:
  • Die Ausdrücke P + J und J + P
  • zeigen auf das i+j -te Element von x , falls i + j in [ 0 , n ) liegt, und
  • sind Zeiger hinter das letzte Element von x , falls i + j gleich n ist.
  • Der Ausdruck P - J
  • zeigt auf das i-j -te Element von x , falls i - j in [ 0 , n ) liegt, und
  • ist ein Zeiger hinter das letzte Element von x , falls i - j gleich n ist.
  • Andere j -Werte führen zu undefiniertem Verhalten.
  • Andernfalls, wenn P auf ein vollständiges Objekt, ein Basisklassen-Subobjekt oder ein Member-Subobjekt y zeigt, und der Wert von J als j gegeben ist, wird P wie folgt addiert oder subtrahiert:
  • Die Ausdrücke P + J und J + P
  • zeigen auf y wenn j gleich 0 ist, und
  • sind Zeiger hinter das Ende von y wenn j gleich 1 ist.
  • Der Ausdruck P - J
  • zeigt auf y wenn j gleich 0 ist, und
  • ist ein Zeiger hinter das Ende von y wenn j gleich - 1 ist.
  • Andere j -Werte führen zu undefiniertem Verhalten.
  • Andernfalls, wenn P ein Zeiger hinter das Ende eines Objekts z ist, mit dem Wert von J als j :
  • Falls z ein Array-Objekt mit n Elementen ist, wird P wie folgt addiert oder subtrahiert:
  • Die Ausdrücke P + J und J + P
  • zeigen auf das n+j -te Element von z , falls n + j in [ 0 , n ) liegt, und
  • sind Zeiger hinter das letzte Element von z , falls j gleich 0 ist.
  • Der Ausdruck P - J
  • zeigt auf das n-j -te Element von z , falls n - j in [ 0 , n ) liegt, und
  • ist ein Zeiger hinter das letzte Element von z , falls 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
  • zeigen auf z , falls j gleich - 1 ist, und
  • sind Zeiger hinter das Ende von z , falls j gleich 0 ist.
  • Der Ausdruck P - J
  • zeigt auf z , falls j gleich 1 ist, und
  • ist ein Zeiger hinter das Ende von z , falls j gleich 0 ist.
  • Andere j -Werte führen zu undefiniertem Verhalten.
  • Andernfalls ist das Verhalten undefiniert.

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

  • Wenn P und Q beide zu Null-Zeigerwerten ausgewertet werden, ist das Ergebnis 0 .
  • Andernfalls, wenn P und Q jeweils auf das i -te und 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-Subobjekt oder Mitglieds-Subobjekt zeigen, ist das Ergebnis 0 .
  • Andernfalls ist das Verhalten undefiniert.

Diese Zeigerarithmetik-Operatoren ermöglichen es Zeigern, die LegacyRandomAccessIterator Anforderungen zu erfüllen.

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

int arr[5] = {1, 2, 3, 4, 5};
unsigned int *p = reinterpret_cast<unsigned int*>(arr + 1);
unsigned int k = *p; // OK, der Wert von "k" ist 2
unsigned int *q = p + 1; // undefiniertes Verhalten: "p" zeigt auf int, nicht unsigned int

Überladungen

Bei Überlagerungsauflösung für benutzerdefinierte Operatoren nehmen für jedes Paar von heraufgestuften arithmetischen Typen L und R und für jeden Objekttyp T die folgenden Funktionssignaturen an der Überlagerungsauflö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 auf 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

Multiplikative Operatoren

Die multiplikativen Operatorausdrücke haben die Form

lhs * rhs (1)
lhs / rhs (2)
lhs % rhs (3)
**Anmerkung:** Da die Anweisung besagt, dass C++-spezifische Begriffe nicht übersetzt werden sollen und der Text innerhalb der ` ` Tags nur aus den C++-Bezeichnern `lhs` und `rhs` besteht, wurden diese nicht übersetzt. Die numerischen Klammern (1), (2), (3) bleiben ebenfalls unverändert, da es sich um technische Referenznummern handelt.
1) Multiplikation.
2) Division.
3) Rest.

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

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

Eingebaute multiplikative Operatoren

Für die eingebauten Multiplikations- und Divisionsoperatoren müssen beide Operanden arithmetischen oder unbegrenzten Aufzählungstyp haben. Für den eingebauten Restoperator müssen beide Operanden ganzzahligen oder unbegrenzten Aufzählungstyp haben. Übliche arithmetische Konvertierungen werden auf beide Operanden angewendet.

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

1) Das Ergebnis der eingebauten 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 ):
  • Multiplikation einer NaN mit einer beliebigen Zahl ergibt NaN.
  • Multiplikation von Unendlich mit Null ergibt NaN und FE_INVALID wird ausgelöst.
2) Das Ergebnis der eingebauten Division ist lhs dividiert 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 in Richtung Null abgeschnitten (der Bruchteil 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.
  • Division einer Zahl ungleich Null durch ±0.0 ergibt das korrekt vorzeichenbehaftete Unendlich und FE_DIVBYZERO wird ausgelöst.
  • Division von 0.0 durch 0.0 ergibt NaN und FE_INVALID wird ausgelöst.
3) Das Ergebnis des eingebauten Restwertoperators 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, dann gilt ( a / b ) * b + a % b == a .
Wenn a / b im Ergebnistyp nicht darstellbar ist, ist das Verhalten von sowohl a / b als auch a % b undefiniert (das bedeutet INT_MIN % - 1 ist auf Zweierkomplement-Systemen undefiniert).

Hinweis: Bis zur Lösung von CWG Issue 614 ( N2757 ) war das Vorzeichen des Restes bei binärem Operator % implementierungsdefiniert, wenn ein oder beide Operanden negativ waren, da es von der Rundungsrichtung der Ganzzahldivision abhängt. Die Funktion std::div bot in diesem Fall wohldefiniertes Verhalten.

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

Überladungen

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

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

wobei LRx das Ergebnis der üblichen arithmetischen Konvertierungen auf 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

Bitweise Logikoperatoren

Die bitweisen logischen Operatorausdrücke haben die Form

~ rhs (1)
lhs & rhs (2)
lhs | rhs (3)
lhs ^ rhs (4)
1) Bitweises NOT.
2) Bitweise UND-Operation.
3) Bitweise ODER-Operation.
4) Bitweises XOR.

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

~a - b; // entspricht (~a) - b, NICHT ~(a - b)
~c * d; // entspricht (~c) * d, NICHT ~(c * d)
~-e; // entspricht ~(-e)

Es gibt eine Mehrdeutigkeit in der Grammatik, wenn ~ von einem Typnamen oder einem decltype -Spezifizierer (seit C++11) gefolgt wird: Es kann sich entweder um operator~ handeln oder um den Beginn eines Destruktor -Identifikators. Die Mehrdeutigkeit wird aufgelöst, indem ~ als operator~ behandelt wird. ~ kann nur an Stellen einen Destruktor-Identifikator beginnen, an denen die Bildung eines operator~ syntaktisch ungültig ist.

Alle anderen bitweisen Logikoperatoren haben eine niedrigere 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;  // entspricht a & (b * c),  NICHT (a & b) * c
d / e ^ f;  // entspricht (d / e) ^ f,  NICHT d / (e ^ f)
g << h | i; // entspricht (g << h) | i, NICHT g << (h | i)
j & k & l; // entspricht (j & k) & l
m | n ^ o  // entspricht m | (n ^ o)

Eingebaute bitweise Logikoperatoren

Für den eingebauten bitweisen NOT-Operator muss rhs ein Prvalue von integralem oder unbegrenztem Aufzählungstyp sein, und es wird eine integrale Promotion auf rhs durchgeführt. Für andere eingebaute bitweise Logikoperatoren müssen beide Operanden integralen oder unbegrenzten Aufzählungstyp haben, und es werden übliche arithmetische Konvertierungen auf beide Operanden angewendet.

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

1) Gegeben sei der Operand als x und das Ergebnis der eingebauten bitweisen NOT-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 gleich 1 , wenn x_i gleich 0 ist, und andernfalls gleich 0 .
  • 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 und y beziehungsweise und das Ergebnis der eingebauten binären bitweisen Logikoperationen als r . Für jedes Paar von Koeffizienten x_i und y_i der Basis-2-Darstellungen von x und y beziehungsweise, ist der entsprechende Koeffizient r_i der Basis-2-Darstellung von r
2) 1 wenn sowohl x_i als auch y_i den Wert 1 haben, und 0 andernfalls.
3) 1 wenn mindestens eines von x_i und y_i gleich 1 ist, und 0 sonst.
4) 1 wenn entweder (aber nicht beide) von x_i und y_i gleich 1 ist, und 0 andernfalls.
Der Typ des Ergebnisses r ist der Typ der Operanden x und y .

Überladungen

Bei Überlagerungsauflösung für benutzerdefinierte Operatoren nehmen für jedes Paar von heraufgestuften Ganzzahltypen L und R die folgenden Funktionssignaturen an der Überlagerungsauflö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 auf 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
              << "Maske: " << mask << std::setw(49) << bin16(mask) << "\n"
                 "Wert: " << x0 << std::setw(42) << bin32(x0) << "\n"
                 "Bits setzen: " << x1 << std::setw(35) << bin32(x1) << "\n"
                 "Bits löschen: " << x2 << std::setw(34) << bin32(x2) << "\n"
                 "Bits auswählen: " << x3 << std::setw(39) << bin32(x3) << "\n"
                 "Bits XOR-en: " << x4 << std::setw(35) << bin32(x4) << "\n"
                 "Bits invertieren: " << x5 << std::setw(33) << bin32(x5) << '\n';
}

Ausgabe:

Maske: 0xf0                                 0000000011110000
Wert: 0x12345678          00010010001101000101011001111000
Bits setzen: 0x123456f8   00010010001101000101011011111000
Bits löschen: 0x12345608  00010010001101000101011000001000
Bits auswählen: 0x70       00000000000000000000000001110000
Bits XOR-en: 0x12345688   00010010001101000101011010001000
Bits invertieren: 0xedcba987 11101101110010111010100110000111

Bitweise Schiebeoperatoren

Die bitweisen Schiebeoperator-Ausdrücke haben die Form

lhs << rhs (1)
lhs >> rhs (2)
**Hinweis:** Da der Text auf der Webseite ausschließlich aus HTML-Tags, C++-Operatoren (`<<` und `>>`) und Platzhaltervariablen (`lhs`, `rhs`) besteht, die gemäß den Anweisungen nicht übersetzt werden sollen, bleibt der Inhalt unverändert. Die numerischen Referenzen (1) und (2) sind ebenfalls unverändert beibehalten.
1) Bitweise Linksverschiebung.
2) Bitweise Rechtsverschiebung.

Bitweise Verschiebeoperatoren haben eine höhere Präzedenz als bitweise Logikoperatoren, aber eine niedrigere Präzedenz als additive und multiplikative Operatoren. Diese Operatoren assoziieren von links nach rechts:

a >> b * c;  // entspricht a >> (b * c),  NICHT (a >> b) * c
d << e & f;  // entspricht (d << e) & f,  NICHT d << (e & f)
g << h >> i; // entspricht (g << h) >> i, NICHT g << (h >> i)

Eingebaute bitweise Verschiebeoperatoren

Für die eingebauten bitweisen Verschiebeoperatoren müssen beide Operanden Prvalues von ganzzahligen oder unbegrenzten Aufzählungstypen sein. Ganzzahlige Höherstufungen werden auf beiden Operanden durchgeführt.

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

Wenn der Wert von rhs negativ ist oder nicht 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 * 2 b
, reduziert modulo 2 N
, wobei N die Anzahl der Bits im Rückgabetyp ist (d.h., es wird ein bitweiser Linksshift durchgeführt und die Bits, die aus dem Zieltyp hinausgeschoben werden, werden verworfen).

Für vorzeichenbehaftete und nicht-negative a , wenn a * 2 b
in der vorzeichenlosen Version des Rückgabetyps darstellbar ist, dann ist dieser Wert, konvertiert zu vorzeichenbehaftet, der Wert von a << b (dies macht es legal, 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 und für vorzeichenbehaftete und nicht-negative a ist der Wert von a >> b der ganzzahlige Teil von a/2 b
.

Für negative a ist der Wert von a >> b implementierungsdefiniert (in den meisten Implementierungen führt dies einen arithmetischen Rechtsshift durch, sodass das Ergebnis negativ bleibt).

(bis C++20)

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

Der Wert von a >> b ist a/2 b
, abgerundet gegen negative Unendlichkeit (mit anderen Worten, der Rechtsshift auf vorzeichenbehaftetem a ist ein arithmetischer Rechtsshift).

(seit C++20)

Der Typ des Ergebnisses ist der von lhs .

Überladungen

Bei Überlagerungsauflösung für benutzerdefinierte Operatoren nehmen für jedes Paar von heraufgestuften Ganzzahltypen L und R die folgenden Funktionssignaturen an der Überlagerungsauflö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" // Überlauf bei unsigned
                 "0x10 << 10 = " << (c << 10) << '\n';   // char wird zu int heraufgestuft
    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

Standardbibliothek

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

Unäre arithmetische Operatoren

implementiert unäres + und unäres -
(öffentliche Elementfunktion von std::chrono::duration<Rep,Period> )
wendet unäre Operatoren auf komplexe Zahlen an
(Funktionstemplate)
wendet einen unären arithmetischen Operator auf jedes Element des valarray an
(öffentliche Elementfunktion von std::valarray<T> )

Additive Operatoren

führt Additions- und Subtraktionsoperationen mit einem Zeitpunkt durch
(Funktions-Template)
implementiert arithmetische Operationen mit Zeitdauern als Argumente
(Funktions-Template)
addiert oder subtrahiert einen year_month_day und eine Anzahl von Jahren oder Monaten
(Funktion)
verkettet zwei Strings, einen String und ein char , oder einen String und string_view
(Funktions-Template)
erhöht oder verringert den Iterator
(öffentliche Member-Funktion von std::reverse_iterator<Iter> )
erhöht oder verringert den Iterator
(öffentliche Member-Funktion von std::move_iterator<Iter> )
führt komplexe Zahlenarithmetik mit zwei komplexen Werten oder einem komplexen Wert und einem Skalar durch
(Funktions-Template)
wendet binäre Operatoren auf jedes Element von zwei Valarrays oder einem Valarray und einem Wert an
(Funktions-Template)

Multiplikative Operatoren

implementiert arithmetische Operationen mit Dauern als Argumente
(Funktions-Template)
führt komplexe Zahlenarithmetik für zwei komplexe Werte oder einen komplexen Wert und einen Skalar aus
(Funktions-Template)
wendet binäre Operatoren auf jedes Element von zwei Valarrays oder einem Valarray und einem Wert an
(Funktions-Template)

Bitweise logische Operatoren

führt binäres UND, ODER, XOR und NICHT aus
(öffentliche Elementfunktion von std::bitset<N> )
führt binäre Logikoperationen auf Bitsets aus
(Funktions-Template)
wendet einen unären arithmetischen Operator auf jedes Element des Valarray an
(öffentliche Elementfunktion von std::valarray<T> )
wendet binäre Operatoren auf jedes Element von zwei Valarrays oder eines Valarray und eines Wertes an
(Funktions-Template)

Bitweise Schiebeoperatoren

Wendet binäre Operatoren auf jedes Element von zwei valarrays oder einem valarray und einem Wert an
(Funktions-Template)
Führt binäre Verschiebung nach links und rechts durch
(Öffentliche Mitgliedsfunktion von std::bitset<N> )

Stream-Einfüge-/Extraktionsoperatoren

In der gesamten Standardbibliothek werden bitweise Schiebeoperatoren häufig mit E/A-Streams ( std:: ios_base & oder einer der davon abgeleiteten Klassen) als linker Operand und Rückgabetyp überladen. Solche Operatoren werden als Stream-Einfügeoperatoren und Stream-Extraktionsoperatoren bezeichnet:

extrahiert formatierte Daten
(öffentliche Elementfunktion von std::basic_istream<CharT,Traits> )
extrahiert Zeichen und Zeichenarrays
(Funktionstemplate)
fügt formatierte Daten ein
(öffentliche Elementfunktion von std::basic_ostream<CharT,Traits> )
fügt Zeichendaten ein oder fügt in Rvalue-Stream ein
(Funktionstemplate)
serialisiert und deserialisiert eine komplexe Zahl
(Funktionstemplate)
führt Stream-Eingabe und -Ausgabe von Bitsets durch
(Funktionstemplate)
führt Stream-Eingabe und -Ausgabe für Strings durch
(Funktionstemplate)
führt Stream-Eingabe und -Ausgabe für Pseudozufallszahlengeneratoren durch
(Funktionstemplate)
führt Stream-Eingabe und -Ausgabe für Pseudozufallszahlenverteilungen durch
(Funktionstemplate)

Fehlerberichte

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

DR Angewendet auf Verhalten wie veröffentlicht Korrektes Verhalten
CWG 614 C++98 der algebraische Quotient der Ganzzahldivision wurde
in implementierungsdefinierter Richtung gerundet
der algebraische Quotient der Ganzzahl-
division wird gegen Null gekürzt
(Nachkommastellen werden verworfen)
CWG 1450 C++98 das Ergebnis von a / b war nicht spezifiziert, wenn
es nicht im Ergebnistyp darstellbar ist
das Verhalten von sowohl a / b als auch
a % b ist in diesem Fall undefiniert
CWG 1457 C++98 das Verhalten beim Verschieben des linkesten 1 Bits eines
positiven vorzeichenbehafteten Werts in das Vorzeichenbit war undefiniert
wohldefiniert gemacht
CWG 1504 C++98 ein Zeiger auf ein Basisklassen-Subobjekt eines Array-
Elements konnte in Zeigerarithmetik verwendet werden
das Verhalten ist
in diesem Fall undefiniert
CWG 1515 C++98 nur vorzeichenlose Ganzzahlen, die mit unsigned
deklariert wurden, sollten den Gesetzen der Arithmetik modulo 2 n
gehorchen
gilt für alle vorzeichenlosen Ganzzahlen
CWG 1642 C++98 arithmetische Operatoren erlaubten, dass ihre Operanden Lvalues sein können einige Operanden müssen Rvalues sein
CWG 1865 C++98 die Lösung von CWG Issue 1504 machte die Verhaltensweisen
der Zeigerarithmetik mit Zeigern auf Array-Elemente
undefiniert, wenn der gezeigte Typ und der Array-Element-
Typ unterschiedliche CV-Qualifikationen in nicht-obersten Ebenen haben
wohldefiniert gemacht
CWG 1971 C++98 es war unklar, ob die Regel zur Auflösung der
Mehrdeutigkeit von ~ auf Fälle wie ~X ( 0 ) anwendbar ist
die Regel ist auf solche Fälle anwendbar
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 ordentliche Definition
das Ergebnis wird in Begriffen
der Basis-2-Darstellung formuliert
CWG 2724 C++20 die Rundungsrichtung des arithmetischen Rechtsschiebens war unklar klargestellt
CWG 2853 C++98 ein Zeiger hinter dem Ende eines Objekts konnte
nicht mit einer Ganzzahl addiert oder subtrahiert werden
es kann

Siehe auch

Operator-Präzedenz

Operatorüberladung

Häufige Operatoren
Zuweisung Inkrement
Dekrement
Arithmetik Logisch Vergleich Member
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
a - > b
a. b
a - > * b
a. * b

Funktionsaufruf

a ( ... )
Komma

a, b
Bedingungsoperator

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 unverwandten Typ
C-style cast konvertiert einen Typ in einen anderen durch eine Kombination von static_cast , const_cast und reinterpret_cast
new erstellt Objekte mit dynamischer Speicherdauer
delete zerstört zuvor durch den new-Ausdruck erstellte Objekte und gibt den bezogenen Speicherbereich frei
sizeof fragt die Größe eines Typs ab
sizeof... fragt die Größe eines Pack ab (seit C++11)
typeid fragt die Typinformationen eines Typs ab
noexcept prüft, ob ein Ausdruck eine Exception werfen kann (seit C++11)
alignof fragt die Ausrichtungsanforderungen eines Typs ab (seit C++11)

C-Dokumentation für Arithmetische Operatoren