Arithmetic operators
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 ) ; | |
|
||||
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.
-ftrapvin 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) | ||||||||
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
-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) | ||||||||
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.
- 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 ).
- 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.
-
zeigen auf das
- 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.
-
zeigt auf das
- 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.
-
zeigen auf das
- 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.
-
zeigt auf das
- 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 undj-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) | ||||||||
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).
- Multiplikation einer NaN mit einer beliebigen Zahl ergibt NaN.
- Multiplikation von Unendlich mit Null ergibt NaN und FE_INVALID wird ausgelöst.
- 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.
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) | ||||||||
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.
- Mit anderen Worten, das Ergebnis ist das Einerkomplement des Operanden (wobei Operand und Ergebnis als vorzeichenlos betrachtet werden).
Ü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) | ||||||||
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
Für vorzeichenbehaftete und nicht-negative
a
, wenn
a * 2
b
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
Der Wert von
a
>>
b
ist
a/2
b
|
(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
|
(C++11)
|
führt Additions- und Subtraktionsoperationen mit einem Zeitpunkt durch
(Funktions-Template) |
|
implementiert arithmetische Operationen mit Zeitdauern als Argumente
(Funktions-Template) |
|
|
(C++20)
|
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) |
|
|
(C++11)
|
führt Stream-Eingabe und -Ausgabe für Pseudozufallszahlengeneratoren durch
(Funktionstemplate) |
|
(C++11)
|
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
| Häufige Operatoren | ||||||
|---|---|---|---|---|---|---|
| Zuweisung |
Inkrement
Dekrement |
Arithmetik | Logisch | Vergleich |
Member
Zugriff |
Sonstige |
|
a
=
b
|
++
a
|
+
a
|
!
a
|
a
==
b
|
a
[
...
]
|
Funktionsaufruf
a ( ... ) |
|
Komma
a, b |
||||||
|
Bedingungsoperator
a ? b : c |
||||||
| Spezielle Operatoren | ||||||
|
static_cast
konvertiert einen Typ in einen anderen verwandten Typ
|
||||||
|
C-Dokumentation
für
Arithmetische Operatoren
|