Namensräume
Varianten
Aktionen

Übliche arithmetische Konvertierungen

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

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

Viele binäre Operatoren, die Operanden vom arithmetischen oder Aufzählungstyp erwarten, führen Konvertierungen durch und liefern auf ähnliche Weise Ergebnistypen. Der Zweck ist, einen gemeinsamen Typ zu erzielen, der auch der Typ des Ergebnisses ist. Dieses Muster wird als die üblichen arithmetischen Konvertierungen bezeichnet.

Inhalt

[bearbeiten] Definition

Die üblichen arithmetischen Konvertierungen sind wie folgt definiert

[bearbeiten] Stufe 1

Auf beide Operanden wird eine Lvalue-zu-Rvalue-Konvertierung angewendet. Die resultierenden prvalues werden anstelle der ursprünglichen Operanden für den restlichen Prozess verwendet.

[bearbeiten] Stufe 2

  • Wenn einer der Operanden vom Typ Scoped Enumeration Type ist, werden keine Konvertierungen durchgeführt. Wenn der andere Operand nicht denselben Typ hat, ist der Ausdruck fehlerhaft.
  • Andernfalls wird mit der nächsten Stufe fortgefahren.
(seit C++11)

[bearbeiten] Stufe 3

  • Wenn einer der Operanden vom Typ Enumeration Type ist und der andere Operand von einem anderen Enumeration Type oder einem Gleitkommatyp ist, ist der Ausdruck fehlerhaft.
  • Andernfalls wird mit der nächsten Stufe fortgefahren.
(seit C++26)

[bearbeiten] Stufe 4

  • Wenn einer der Operanden vom Typ Floating-point Type ist, werden die folgenden Regeln angewendet
  • Wenn beide Operanden denselben Typ haben, wird keine weitere Konvertierung durchgeführt.
  • Andernfalls, wenn einer der Operanden von einem Nicht-Gleitkommatyp ist, wird dieser Operand in den Typ des anderen Operanden konvertiert.
  • Andernfalls, wenn die Gleitkommakonvertierungsränge der Typen der Operanden geordnet, aber(seit C++23) nicht gleich sind, dann wird der Operand vom Typ mit dem geringeren Gleitkommakonvertierungsrang in den Typ des anderen Operanden konvertiert.
  • Andernfalls, wenn die Gleitkommakonvertierungsränge der Typen der Operanden gleich sind, dann wird der Operand mit dem geringeren Gleitkommakonvertierungsunterrang in den Typ des anderen Operanden konvertiert.
  • Andernfalls ist der Ausdruck fehlerhaft.
(seit C++23)
  • Andernfalls sind beide Operanden von Ganzzahltypen, und es wird mit der nächsten Stufe fortgefahren.

[bearbeiten] Stufe 5

Beide Operanden werden in einen gemeinsamen Typ C konvertiert. Gegeben die Typen T1 und T2 als der beförderte Typ (gemäß den Regeln der Integral Promotion) der Operanden, werden die folgenden Regeln angewendet, um C zu bestimmen

  • Wenn T1 und T2 derselben Typ sind, ist C dieser Typ.
  • Andernfalls, wenn T1 und T2 beide vorzeichenbehaftete Ganzzahltypen oder beide vorzeichenlose Ganzzahltypen sind, ist C der Typ mit dem größeren Rang der Ganzzahlkonvertierung.
  • Andernfalls ist ein Typ zwischen T1 und T2 ein vorzeichenbehafteter Ganzzahltyp S und der andere Typ ist ein vorzeichenloser Ganzzahltyp U. Wenden Sie die folgenden Regeln an
  • Wenn der Rang der Ganzzahlkonvertierung von U größer oder gleich dem Rang der Ganzzahlkonvertierung von S ist, ist C U.
  • Andernfalls, wenn S alle Werte von U darstellen kann, ist C S.
  • Andernfalls ist C der vorzeichenlose Ganzzahltyp, der S entspricht.

Wenn ein Operand vom Enumerationstyp und der andere Operand von einem anderen Enumerationstyp oder einem Gleitkommatyp ist, ist dieses Verhalten veraltet.

(seit C++20)
(bis C++26)

[bearbeiten] Rang der Ganzzahlkonvertierung

Jeder Ganzzahltyp hat einen Rang der Ganzzahlkonvertierung, der wie folgt definiert ist

  • Keine zwei vorzeichenbehafteten Ganzzahltypen außer char und signed char (wenn char vorzeichenbehaftet ist) haben denselben Rang, auch wenn sie dieselbe Darstellung haben.
  • Der Rang eines vorzeichenbehafteten Ganzzahltyps ist größer als der Rang eines jeden vorzeichenbehafteten Ganzzahltyps mit geringerer Breite.
  • Die Ränge der folgenden Ganzzahltypen nehmen in der Reihenfolge ab
  • long long
(seit C++11)
  • long
  • int
  • short
  • signed char
  • Der Rang eines jeden vorzeichenlosen Ganzzahltyps entspricht dem Rang des entsprechenden vorzeichenbehafteten Ganzzahltyps.
  • Der Rang eines jeden Standard-Ganzzahltyps ist größer als der Rang eines jeden erweiterten Ganzzahltyps mit derselben Breite.
(seit C++11)
  • Der Rang von bool ist kleiner als der Rang aller Standard-Ganzzahltypen.
  • Die Ränge von Codierungszeichentypen (char , char8_t(seit C++20), char16_t, char32_t,(seit C++11) und wchar_t) entsprechen den Rängen ihrer zugrunde liegenden Typen, was bedeutet
  • Der Rang von char entspricht dem Rang von signed char und unsigned char.
  • Der Rang von char8_t entspricht dem Rang von unsigned char.
(seit C++20)
(seit C++11)
  • Der Rang von wchar_t entspricht dem Rang seines implementierungsdefinierten zugrunde liegenden Typs.
  • Der Rang eines jeden erweiterten vorzeichenbehafteten Ganzzahltyps im Verhältnis zu einem anderen erweiterten vorzeichenbehafteten Ganzzahltyp mit derselben Breite ist implementierungsdefiniert, unterliegt aber dennoch den anderen Regeln zur Bestimmung des Rangs der Ganzzahlkonvertierung.
(seit C++11)
  • Für alle Ganzzahltypen T1, T2 und T3 gilt: Wenn T1 einen größeren Rang als T2 und T2 einen größeren Rang als T3 hat, dann hat T1 einen größeren Rang als T3.

Der Rang der Ganzzahlkonvertierung wird auch in der Definition der Integral Promotion verwendet.

[bearbeiten] Gleitkommakonvertierungsrang und Unterrang

[bearbeiten] Gleitkommakonvertierungsrang

Jeder Gleitkommatyp hat einen Gleitkommakonvertierungsrang, der wie folgt definiert ist

  • Die Ränge der Standard-Gleitkommatypen nehmen in der Reihenfolge ab
    • long double
    • double
    • float
  • Der Rang eines Gleitkommatyps T ist größer als der Rang eines jeden Gleitkommatyps, dessen Wertemenge eine echte Teilmenge der Wertemenge von T ist.
  • Zwei erweiterte Gleitkommatypen mit derselben Wertemenge haben gleiche Ränge.
  • Ein erweiterter Gleitkommatyp mit derselben Wertemenge wie genau ein cv-unqualifizierter Standard-Gleitkommatyp hat einen Rang, der dem Rang dieses Standard-Gleitkommatyps entspricht.
  • Ein erweiterter Gleitkommatyp mit derselben Wertemenge wie mehr als ein cv-unqualifizierter Standard-Gleitkommatyp hat einen Rang, der dem Rang von double entspricht.
(seit C++23)


Gleitkommakonvertierungsunterrang

Gleitkommatypen, die gleiche Gleitkommakonvertierungsränge haben, werden nach dem Gleitkommakonvertierungsunterrang geordnet. Der Unterrang bildet eine Totalordnung unter Typen mit gleichen Rängen.

Die Typen std::float16_t, std::float32_t, std::float64_t und std::float128_t (Floating-Point-Typen mit fester Breite) haben einen höheren Konvertierungsunterrang als jeder Standard-Gleitkommatyp mit gleichem Konvertierungsrang. Andernfalls ist die Reihenfolge der Konvertierungsunterränge implementierungsdefiniert.

(seit C++23)

[bearbeiten] Verwendung

Der Gleitkommakonvertierungsrang und der Unterrang werden auch verwendet, um

(seit C++23)

[bearbeiten] Fehlerberichte

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

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
CWG 1642 C++98 übliche arithmetische Konvertierungen können Lvalues beinhalten wenden Lvalue-zu-Rvalue-Konvertierungen zuerst an
CWG 2528 C++20 der Drei-Wege-Vergleich zwischen unsigned char
und unsigned int ist fehlerhaft, da
die Zwischen-Integral-Promotion[1]
bestimmt den gemeinsamen Typ basierend
auf den beförderten Typen, ohne
die Operanden tatsächlich zu befördern[2]
CWG 2892 C++98 wenn beide Operanden vom selben
Gleitkommatyp sind, war die Bedeutung von „keine
weitere Konvertierung nötig“ unklar
geändert zu „keine weitere
Konvertierung wird durchgeführt“
  1. Vor der Auflösung wird unsigned char zu Beginn von Stufe 5 zu int befördert und dann in unsigned int konvertiert. Die letztere Konvertierung ist jedoch schmalend, was den Drei-Wege-Vergleich fehlerhaft macht.
  2. Nach der Auflösung ist der gemeinsame Typ immer noch unsigned int. Der Unterschied besteht darin, dass unsigned char direkt in unsigned int konvertiert wird, ohne die Zwischen-Integral-Promotion. Die Konvertierung ist nicht schmalend und daher ist der Drei-Wege-Vergleich wohlgeformt.