Namespaces
Variants

Implicit conversions

From cppreference.net

Wenn ein Ausdruck in einem Kontext verwendet wird, in dem ein Wert eines anderen Typs erwartet wird, Konvertierung kann auftreten:

int n = 1L; // Ausdruck 1L hat Typ long, int wird erwartet
n = 2.1; // Ausdruck 2.1 hat Typ double, int wird erwartet
char* p = malloc(10); // Ausdruck malloc(10) hat Typ void*, char* wird erwartet

Konvertierungen finden in den folgenden Situationen statt:

Inhaltsverzeichnis

Konvertierung wie durch Zuweisung

  • Im Zuweisungsoperator wird der Wert des rechten Operanden in den uneingeschränkten Typ des linken Operanden konvertiert.
  • Bei der Skalarinitialisierung wird der Wert des Initialisierungsausdrucks in den uneingeschränkten Typ des zu initialisierenden Objekts konvertiert.
  • In einem Funktionsaufrufausdruck , an eine Funktion mit Prototyp, wird der Wert jedes Argumentausdrucks in den Typ der uneingeschränkten deklarierten Typen des entsprechenden Parameters konvertiert.
  • In einer return-Anweisung wird der Wert des Operanden von return in ein Objekt mit dem Rückgabetyp der Funktion konvertiert.

Beachten Sie, dass die tatsächliche Zuweisung zusätzlich zur Konvertierung auch überflüssigen Bereich und Präzision von Gleitkommatypen entfernt und Überlappungen verbietet; diese Eigenschaften gelten nicht für die Konvertierung wie durch Zuweisung.

Standardargument-Promotionen

In einem Funktionsaufrufausdruck wenn der Aufruf erfolgt an

1) eine Funktion ohne Prototyp (bis C23) ,
2) eine variadic function , bei der der Argumentausdruck eines der nachfolgenden Argumente ist, die mit dem Ellipsen-Parameter abgeglichen werden.

Jedes Argument vom Ganzzahltyp durchläuft Integer-Promotion , und jedes Argument vom Typ float wird implizit zum Typ double konvertiert.

int add_nums(int count, ...);
int sum = add_nums(2, 'c', true); // add_nums wird mit drei int-Werten aufgerufen: (2, 99, 1)

Beachten Sie, dass float complex und float imaginary in diesem Kontext nicht zu double complex und double imaginary heraufgestuft werden.

(seit C99)

Übliche arithmetische Konvertierungen

Die Argumente der folgenden arithmetischen Operatoren durchlaufen implizite Konvertierungen, um den gemeinsamen Realtyp  zu erhalten, welcher der Typ ist, in dem die Berechnung durchgeführt wird:

1) Wenn ein Operand Dezimal-Gleitkommatyp hat, darf der andere Operand keinen Standard-Gleitkommatyp,

komplexen oder imaginären Typ haben.

  • Zuerst, wenn der Typ eines der Operanden _Decimal128 ist, wird der andere Operand zu _Decimal128 konvertiert.
  • Andernfalls, wenn der Typ eines der Operanden _Decimal64 ist, wird der andere Operand zu _Decimal64 konvertiert.
  • Andernfalls, wenn der Typ eines der Operanden _Decimal32 ist, wird der andere Operand zu _Decimal32 konvertiert.
(seit C23)
2) Andernfalls, wenn ein Operand long double , long double complex , oder long double imaginary (seit C99) ist, wird der andere Operand implizit wie folgt konvertiert:
  • Ganzzahl- oder Gleitkommatyp zu long double
(seit C99)
3) Andernfalls, wenn ein Operand double , double complex , oder double imaginary (seit C99) ist, wird der andere Operand implizit wie folgt konvertiert:
  • Ganzzahl- oder Gleitkommatyp zu double
(seit C99)
4) Andernfalls, falls ein Operand float , float complex , oder float imaginary (seit C99) ist, wird der andere Operand implizit wie folgt konvertiert:
  • Ganzzahltyp zu float (der einzig mögliche reale Typ ist float, der unverändert bleibt)
(seit C99)
5) Andernfalls sind beide Operanden Ganzzahlen. Beide Operanden durchlaufen Integer-Promotions ; dann, nach Integer-Promotion, trifft einer der folgenden Fälle zu:
  • Wenn die Typen identisch sind, ist dieser Typ der gemeinsame Typ.
  • Andernfalls sind die Typen unterschiedlich:
    • Wenn die Typen die gleiche Vorzeichenbehaftung haben (beide vorzeichenbehaftet oder beide vorzeichenlos), wird der Operand, dessen Typ den geringeren Konvertierungsrang  [1] hat, implizit konvertiert [2] in den anderen Typ.
    • Andernfalls haben die Operanden unterschiedliche Vorzeichenbehaftung:
      • Wenn der vorzeichenlose Typ einen Konvertierungsrang größer oder gleich dem Rang des vorzeichenbehafteten Typs hat, dann wird der Operand mit dem vorzeichenbehafteten Typ implizit in den vorzeichenlosen Typ konvertiert.
      • Andernfalls hat der vorzeichenlose Typ einen Konvertierungsrang kleiner als der vorzeichenbehaftete Typ:
        • Wenn der vorzeichenbehaftete Typ alle Werte des vorzeichenlosen Typs darstellen kann, dann wird der Operand mit dem vorzeichenlosen Typ implizit in den vorzeichenbehafteten Typ konvertiert.
        • Andernfalls durchlaufen beide Operanden eine implizite Konvertierung in den vorzeichenlosen Gegenpart des Typs des vorzeichenbehafteten Operanden.
  1. Siehe Integer-Promotions unten für die Regeln zur Rangbestimmung.
  2. Siehe "Ganzzahlkonvertierungen" unter implizite Konvertierungssemantik unten.
1.f + 20000001; // int wird zu float konvertiert, ergibt 20000000.00
                // Addition und anschließende Rundung auf float ergibt 20000000.00
(char)'a' + 1L; // zuerst wird char 'a', welches 97 ist, zu int heraufgestuft
                // verschiedene Typen: int und long
                // gleiche Vorzeichenbehaftung: beide vorzeichenbehaftet
                // unterschiedlicher Rang: long hat höheren Rang als int
                // daher wird int 97 zu long 97 konvertiert
                // das Ergebnis ist 97 + 1 = 98 vom Typ signed long
2u - 10; // verschiedene Typen: unsigned int und signed int
         // unterschiedliche Vorzeichenbehaftung
         // gleicher Rang
         // daher wird signed int 10 zu unsigned int 10 konvertiert
         // da die arithmetische Operation für vorzeichenlose Ganzzahlen durchgeführt wird
         // (siehe Thema "Arithmetische Operatoren"), wird die Berechnung (2 - 10)
         // modulo (2 hoch n) durchgeführt, wobei n die Anzahl der Wertbits von unsigned int ist
         // wenn unsigned int 32-Bit lang ist und keine Füllbits in seiner Objektdarstellung vorhanden sind
         // dann ist das Ergebnis (-8) modulo (2 hoch 32) = 4294967288
         // vom Typ unsigned int
5UL - 2ULL; // verschiedene Typen: unsigned long und unsigned long long
            // gleiche Vorzeichenbehaftung
            // unterschiedlicher Rang: Rang von unsigned long long ist höher
            // daher wird unsigned long 5 zu unsigned long long 5 konvertiert
            // da die arithmetische Operation für vorzeichenlose Ganzzahlen durchgeführt wird
            // (siehe Thema "Arithmetische Operatoren"),
            // wenn unsigned long long 64-Bit lang ist, dann
            // ist das Ergebnis (5 - 2) modulo (2 hoch 64) = 3 vom Typ
            // unsigned long long
0UL - 1LL; // verschiedene Typen: unsigned long und signed long long
           // unterschiedliche Vorzeichenbehaftung
           // unterschiedlicher Rang: Rang von signed long long ist höher
           // wenn ULONG_MAX > LLONG_MAX, dann kann signed long long nicht alle
           // unsigned long Werte darstellen, daher ist dies der letzte Fall: beide Operanden werden
           // zu unsigned long long konvertiert unsigned long 0 wird zu unsigned long long 0 konvertiert
           // long long 1 wird zu unsigned long long 1 konvertiert da die arithmetische
           // Operation für vorzeichenlose Ganzzahlen durchgeführt wird
           // (siehe Thema "Arithmetische Operatoren"),
           // wenn unsigned long long 64-Bit lang ist, dann
           // ist die Berechnung (0 - 1) modulo (2 hoch 64)
           // somit ist das Ergebnis 18446744073709551615 (ULLONG_MAX) vom Typ
           // unsigned long long

Der Ergebnistyp wird wie folgt bestimmt:

  • wenn beide Operanden komplex sind, ist der Ergebnistyp komplex;
  • wenn beide Operanden imaginär sind, ist der Ergebnistyp imaginär;
  • wenn beide Operanden reell sind, ist der Ergebnistyp reell;
  • wenn die beiden Gleitkomma-Operanden unterschiedliche Typdomänen haben (komplex vs. reell, komplex vs. imaginär oder imaginär vs. reell), ist der Ergebnistyp komplex.
double complex z = 1 + 2*I;
double f = 3.0;
z + f; // z remains as-is, f is converted to double, the result is double complex
(seit C99)

Wie immer kann das Ergebnis eines Gleitkomma-Operators einen größeren Bereich und höhere Genauigkeit haben als durch seinen Typ angegeben (siehe FLT_EVAL_METHOD ).

Hinweis: Reale und imaginäre Operanden werden nicht implizit in komplexe Zahlen konvertiert, da dies zusätzliche Berechnungen erfordern würde und in bestimmten Fällen mit Unendlichkeiten, NaNs und vorzeichenbehafteten Nullen unerwünschte Ergebnisse liefern könnte. Zum Beispiel würde 2.0×(3.0+i∞), wenn reale Zahlen in komplexe konvertiert würden, als (2.0+i0.0)×(3.0+i∞) ⇒ (2.0×3.0–0.0×∞) + i(2.0×∞+0.0×3.0) ⇒ NaN+i∞ ausgewertet werden, anstatt des korrekten 6.0+i∞. Wenn imaginäre Zahlen in komplexe konvertiert würden, würde i2.0×(∞+i3.0) als (0.0+i2.0) × (∞+i3.0) ⇒ (0.0×∞ – 2.0×3.0) + i(0.0×3.0 + 2.0×∞) ⇒ NaN + i∞ anstatt –6.0 + i∞ ausgewertet werden.

(seit C99)

Hinweis: Ungeachtet der üblichen arithmetischen Konvertierungen kann die Berechnung gemäß der as-if rule stets in einem schmaleren Typ durchgeführt werden, als durch diese Regeln spezifiziert.

Werttransformationen

Lvalue-Konvertierung

Jeder Lvalue-Ausdruck eines beliebigen Nicht-Array-Typs, wenn er in einem anderen Kontext als

unterliegt einer Lvalue-Konvertierung  : Der Typ bleibt gleich, verliert jedoch const -/ volatile -/ restrict -Qualifizierer und atomic -Eigenschaften, falls vorhanden. Der Wert bleibt gleich, verliert jedoch seine Lvalue-Eigenschaften (die Adresse kann möglicherweise nicht mehr genommen werden).

Wenn der L-Wert einen unvollständigen Typ hat, ist das Verhalten undefiniert.

Wenn der L-Wert ein Objekt mit automatischer Speicherdauer bezeichnet, dessen Adresse niemals genommen wurde und das nicht initialisiert war (nicht mit einem Initialisierer deklariert und vor der Verwendung keine Zuweisung daran durchgeführt wurde), ist das Verhalten undefiniert.

Diese Konvertierung modelliert den Speicherzugriff des Wertes des Objekts von seinem Speicherort.

volatile int n = 1;
int x = n;            // Lvalue-Konvertierung auf n liest den Wert von n
volatile int* p = &n; // Keine Lvalue-Konvertierung: liest nicht den Wert von n

Array-zu-Zeiger-Konvertierung

Jeder Lvalue-Ausdruck (bis C99) Ausdruck (seit C99) vom Typ Array , wenn verwendet in einem Kontext außerhalb von

unterzieht sich einer Konvertierung zum Nicht-Lvalue-Zeiger auf sein erstes Element.

Wenn das Array als register deklariert wurde, ist das Verhalten undefiniert.

Ein Nicht-Lvalue-Array oder eines seiner Elemente , ist nicht zugreifbar (bis C99) , hat temporäre Lebensdauer (seit C99) .

int a[3], b[3][4];
int* p = a;      /* Konvertierung zu &a[0] */
int (*q)[4] = b; /* Konvertierung zu &b[0] */
struct S
{
    int a[1];
};
struct S f(void)
{
    struct S result = {{0}}; /* {0} seit C99 */
    return result;
}
void g(void)
{
    int* p = f().a;    /* Fehler bis C99; OK seit C99 */
    int n  = f().a[0]; /* Fehler bis C99; OK seit C99 */
    f().a[0] = 13;     /* Fehler bis C99; UB seit C99 */
    (void)p, (void)n;
}
int main(void) { return 0; }

Funktions-zu-Zeiger-Konvertierung

Jeder Funktionsbezeichner-Ausdruck, wenn er in einem anderen Kontext als

unterliegt einer Konvertierung zum Nicht-Lvalue-Zeiger auf die durch den Ausdruck bezeichnete Funktion.

int f(int);
int (*p)(int) = f; // Konvertierung zu &f
(***p)(1); // wiederholte Dereferenzierung zu f und Rückkonvertierung zu &f

Semantik impliziter Konvertierung

Implizite Konvertierung, ob wie durch Zuweisung  oder eine übliche arithmetische Konvertierung  , besteht aus zwei Stufen:

1) Werttransformation (falls zutreffend),
2) eine der unten aufgeführten Konversionen (falls sie den Zieltyp erzeugen kann).

Kompatible Typen

Die Umwandlung eines Werts beliebigen Typs in einen beliebigen kompatiblen Typ ist immer ein No-Op und ändert die Darstellung nicht.

uint8_t (*a)[10];         // falls uint8_t ein Typedef für unsigned char ist
unsigned char (*b)[] = a; // dann sind diese Zeigertypen kompatibel

Ganzzahlige Höherstufungen

Integer Promotion ist die implizite Konvertierung eines Werts eines beliebigen Ganzzahltyps mit Rang kleiner oder gleich dem Rang von int oder eines Bitfelds vom Typ _Bool (bis C23) bool (seit C23) , int , signed int , unsigned int , in den Wert vom Typ int oder unsigned int .

Wenn int den gesamten Wertebereich des ursprünglichen Typs (oder den Wertebereich des ursprünglichen Bitfelds) darstellen kann, wird der Wert in den Typ int konvertiert. Andernfalls wird der Wert in unsigned int konvertiert.

Der Wert aus einem Bitfeld eines bitgenauen Ganzzahltyps wird in den entsprechenden bitgenauen Ganzzahltyp konvertiert. Andernfalls sind bitgenaue Ganzzahltypen von den Ganzzahl-Höherwertigkeitsregeln ausgenommen.

(seit C23)

Integer-Promotions bewahren den Wert, einschließlich des Vorzeichens:

int main(void)
{
    void f(); // alte Funktionsdeklaration
              // seit C23 hat void f(...) dasselbe Verhalten bezüglich Promotions
    char x = 'a'; // Integer-Konvertierung von int zu char
    f(x); // Integer-Promotion von char zurück zu int
}
void f(x) int x; {} // die Funktion erwartet int

rank oben ist eine Eigenschaft jedes integer type und ist wie folgt definiert:

1) die Ränge aller vorzeichenbehafteten Ganzzahltypen sind unterschiedlich und steigen mit ihrer Präzision: Rang von signed char < Rang von short < Rang von int < Rang von long int < Rang von long long int
2) die Ränge aller vorzeichenbehafteten Ganzzahltypen entsprechen den Rängen der entsprechenden vorzeichenlosen Ganzzahltypen
3) der Rang jedes Standard-Ganzzahltyps ist größer als der Rang jedes erweiterten Ganzzahltyps oder bitgenauen Ganzzahltyps (seit C23) derselben Größe (d.h. Rang von __int64 < Rang von long long int , aber Rang von long long < Rang von __int128 aufgrund der Regel (1) )
4) Rang von char entspricht Rang von signed char und Rang von unsigned char
5) der Rang von _Bool (until C23) bool (since C23) ist geringer als der Rang jedes anderen standardmäßigen Ganzzahltyps
6) der Rang eines jeden Aufzählungstyps entspricht dem Rang seines kompatiblen Integer-Typs
7) Rangfolge ist transitiv: wenn Rang von T1 < Rang von T2 und Rang von T2 < Rang von T3 dann Rang von T1 < Rang von T3.
8) der Rang eines bitgenauen vorzeichenbehafteten Ganzzahltyps muss größer sein als der Rang jedes Standard-Ganzzahltyps mit geringerer Breite oder jedes bitgenauen Ganzzahltyps mit geringerer Breite.
9) der Rang jedes bitgenauen Ganzzahltyps relativ zu einem erweiterten Ganzzahltyp derselben Breite ist implementierungsdefiniert.
(seit C23)
10) Alle Aspekte der relativen Rangfolge erweiterter Ganzzahltypen, die oben nicht behandelt wurden, sind implementierungsdefiniert.

Hinweis: Ganzzahlaufwertungen werden nur angewendet

  • als Teil der üblichen arithmetischen Konvertierungen (siehe oben),
  • als Teil der Standardargument-Promotions (siehe oben),
  • für den Operanden der unären arithmetischen Operatoren + und - ,
  • für den Operanden des unären bitweisen Operators ~ ,
  • für beide Operanden der Schiebeoperatoren << und >> .

Boolesche Konvertierung

Ein Wert jedes skalaren Typs kann implizit konvertiert werden zu _Bool (bis C23) bool (seit C23) . Die Werte, die gleich einem ganzzahligen konstanten Ausdruck mit Wert Null sind (bis C23) Null (für arithmetische Typen), null (für Zeigertypen) sind oder den Typ nullptr_t haben (seit C23) , werden konvertiert zu 0 (bis C23) false (seit C23) , alle anderen Werte werden konvertiert zu 1 (bis C23) true (seit C23) .

bool b1 = 0.5;              // b1 == 1 (0.5 converted to int would be zero)
bool b2 = 2.0*_Imaginary_I; // b2 == 1 (but converted to int would be zero)
bool b3 = 0.0 + 3.0*I;      // b3 == 1 (but converted to int would be zero)
bool b4 = 0.0 / 0.0;        // b4 == 1 (NaN does not compare equal to zero)
bool b5 = nullptr;          // b5 == 0 (since C23: nullptr is converted to false)
(seit C99)

Integer-Konvertierungen

Ein Wert jedes ganzzahligen Typs kann implizit in jeden anderen ganzzahligen Typ konvertiert werden. Außer in den Fällen, die durch die oben genannten Höherstufungen und booleschen Konvertierungen abgedeckt sind, gelten folgende Regeln:

  • wenn der Zieltyp den Wert darstellen kann, bleibt der Wert unverändert,
  • andernfalls, wenn der Zieltyp vorzeichenlos ist, wird der Wert 2 b
    , wobei b die Anzahl der Wertbits im Zieltyp ist, wiederholt vom Quellwert subtrahiert oder zu ihm addiert, bis das Ergebnis in den Zieltyp passt. Mit anderen Worten, vorzeichenlose Ganzzahlen implementieren Modulo-Arithmetik.
  • andernfalls, wenn der Zieltyp vorzeichenbehaftet ist, ist das Verhalten implementierungsdefiniert (was das Auslösen eines Signals beinhalten kann).
char x = 'a'; // int → char, Ergebnis unverändert
unsigned char n = -123456; // Ziel ist unsigned, Ergebnis ist 192 (d.h. -123456+483*256)
signed char m = 123456;    // Ziel ist signed, Ergebnis ist implementierungsdefiniert
assert(sizeof(int) > -1);  // assert schlägt fehl:
                           // operator > erfordert Konvertierung von -1 zu size_t,
                           // Ziel ist unsigned, Ergebnis ist SIZE_MAX

Reale Gleitkomma-Ganzzahl-Konvertierungen

Ein endlicher Wert jedes reellen Gleitkommatyps kann implizit in jeden Ganzzahltyp konvertiert werden. Außer in den Fällen, die bereits durch die oben beschriebene boolesche Konvertierung abgedeckt sind, gelten folgende Regeln:

  • Der Bruchteil wird verworfen (abgeschnitten in Richtung Null).
  • Wenn der resultierende Wert durch den Zieltyp dargestellt werden kann, wird dieser Wert verwendet
  • andernfalls ist das Verhalten undefiniert.
int n = 3.14; // n == 3
int x = 1e10; // undefiniertes Verhalten für 32-Bit int

Ein Wert jedes ganzzahligen Typs kann implizit in jeden Gleitkommatyp mit reellen Zahlen konvertiert werden.

  • wenn der Wert exakt durch den Zieltyp dargestellt werden kann, bleibt er unverändert.
  • wenn der Wert dargestellt werden kann, aber nicht exakt, ist das Ergebnis eine implementierungsdefinierte Wahl entweder des nächsthöheren oder nächstniedrigeren Wertes, obwohl bei IEEE-Arithmetik-Unterstützung auf den nächsten Wert gerundet wird. Es ist nicht spezifiziert, ob FE_INEXACT in diesem Fall ausgelöst wird.
  • wenn der Wert nicht dargestellt werden kann, ist das Verhalten undefiniert, obwohl bei IEEE-Arithmetik-Unterstützung FE_INVALID ausgelöst wird und der Ergebniswert nicht spezifiziert ist.

Das Ergebnis dieser Konvertierung kann einen größeren Wertebereich und höhere Genauigkeit aufweisen, als der Zieltyp angibt (siehe FLT_EVAL_METHOD ).

Wenn Kontrolle über FE_INEXACT bei Gleitkomma-zu-Ganzzahl-Konvertierungen benötigt wird, können rint und nearbyint verwendet werden.

double d = 10; // d = 10.00
float f = 20000001; // f = 20000000.00 (FE_INEXACT)
float x = 1 + (long long)FLT_MAX; // undefiniertes Verhalten

Konvertierungen von Gleitkommazahlen

Ein Wert jedes reellen Gleitkommatyps kann implizit in jeden anderen reellen Gleitkommatyp konvertiert werden.

  • Wenn der Wert exakt durch den Zieltyp dargestellt werden kann, bleibt er unverändert.
  • Wenn der Wert dargestellt werden kann, aber nicht exakt, ist das Ergebnis der nächsthöhere oder nächstniedrigere Wert (mit anderen Worten, die Rundungsrichtung ist implementierungsdefiniert), obwohl bei IEEE-Arithmetik die Rundung zur nächsten Zahl erfolgt.
  • Wenn der Wert nicht dargestellt werden kann, ist das Verhalten undefiniert .

Das Ergebnis dieser Konvertierung kann einen größeren Bereich und höhere Genauigkeit aufweisen, als der Zieltyp angibt (siehe FLT_EVAL_METHOD ).

double d = 0.1; // d = 0.1000000000000000055511151231257827021181583404541015625
float f = d;    // f = 0.100000001490116119384765625
float x = 2 * (double)FLT_MAX; // undefiniert

Komplexe Typkonvertierungen

Ein Wert jedes komplexen Typs kann implizit in jeden anderen komplexen Typ konvertiert werden. Der Realteil und der Imaginärteil folgen einzeln den Konvertierungsregeln für die reellen Fließkommatypen.

double complex d = 0.1 + 0.1*I;
float complex f = d; // f ist (0.100000001490116119384765625, 0.100000001490116119384765625)

Imaginäre Typkonvertierungen

Ein Wert jedes imaginären Typs kann implizit in jeden anderen imaginären Typ konvertiert werden. Der Imaginärteil folgt den Konvertierungsregeln für die reellen Fließkommatypen.

double imaginary d = 0.1*_Imaginary_I;
float imaginary f = d; // f ist 0.100000001490116119384765625*I

Real-Komplex-Konvertierungen

Ein Wert jedes reellen Fließkommatyps kann implizit in jeden komplexen Typ konvertiert werden.

  • Der Realteil des Ergebnisses wird durch die Konvertierungsregeln für die reellen Fließkommatypen bestimmt.
  • Der Imaginärteil des Ergebnisses ist positive Null (oder vorzeichenlose Null auf Nicht-IEEE-Systemen).

Ein Wert jedes komplexen Typs kann implizit in jeden reellen Fließkommatyp konvertiert werden.

  • Der Realteil wird nach den Regeln für die reellen Fließkommatypen konvertiert.
  • Der Imaginärteil wird verworfen.

Hinweis: Bei der Komplex-zu-Real-Konvertierung wird ein NaN im Imaginärteil nicht an das Realergebnis weitergegeben.

double complex z = 0.5 + 3*I;
float f = z;  // der Imaginärteil wird verworfen, f wird auf 0.5 gesetzt
z = f;        // setzt z auf 0.5 + 0*I

Real-Imaginär-Konvertierungen

Ein Wert jedes imaginären Typs kann implizit in jeden reellen Typ (Ganzzahl oder Fließkomma) konvertiert werden. Das Ergebnis ist immer eine positive (oder vorzeichenlose) Null, außer wenn der Zieltyp _Bool (bis C23) bool (seit C23) ist, in welchem Fall die booleschen Konvertierungsregeln angewendet werden.

Ein Wert jedes reellen Typs kann implizit in jeden imaginären Typ konvertiert werden. Das Ergebnis ist immer eine positive imaginäre Null.

double imaginary z = 3*I;
bool b = z;  // Boolesche Konvertierung: setzt b auf true 
float f = z; // Real-Imaginär-Konvertierung: setzt f auf 0.0 
z = 3.14;    // Imaginär-Real-Konvertierung: setzt z auf 0*_Imaginary_I

Komplex-Imaginär-Konvertierungen

Ein Wert jedes imaginären Typs kann implizit in jeden komplexen Typ konvertiert werden.

  • Der Realteil des Ergebnisses ist die positive Null.
  • Der Imaginärteil des Ergebnisses folgt den Konvertierungsregeln für die entsprechenden reellen Typen.

Ein Wert jedes komplexen Typs kann implizit in jeden imaginären Typ konvertiert werden.

  • Der Realteil wird verworfen.
  • Der Imaginärteil des Ergebnisses folgt den Konvertierungsregeln für die entsprechenden reellen Typen.
double imaginary z = I * (3*I); // das komplexe Ergebnis -3.0+0i verliert den Realteil
                                // setzt z auf 0*_Imaginary_I
(seit C99)

Zeigerkonvertierungen

Ein Zeiger auf void kann implizit zu und von jedem Zeiger auf einen Objekttyp mit der folgenden Semantik konvertiert werden:

  • Wenn ein Zeiger auf ein Objekt in einen Zeiger auf void konvertiert und zurückkonvertiert wird, vergleicht sich sein Wert gleich mit dem ursprünglichen Zeiger.
  • Es werden keine weiteren Garantien angeboten.
int* p = malloc(10 * sizeof(int)); // malloc gibt void* zurück

Ein Zeiger auf einen uneingeschränkten Typ kann implizit in den Zeiger auf die qualifizierte Version dieses Typs konvertiert werden (mit anderen Worten, const , volatile , und restrict Qualifizierer können hinzugefügt werden). Der ursprüngliche Zeiger und das Ergebnis vergleichen sich gleich.

int n;
const int* p = &n; // &n hat den Typ int*

Jeder ganzzahlige konstante Ausdruck mit dem Wert 0 sowie jeder ganzzahlige Zeigerausdruck mit dem Wert Null, der in den Typ void * umgewandelt wird, kann implizit in jeden Zeigertyp konvertiert werden (sowohl Zeiger auf Objekt als auch Zeiger auf Funktion). Das Ergebnis ist der Nullzeigerwert seines Typs, der garantiert ungleich jedem Nicht-Null-Zeigerwert dieses Typs ist. Dieser ganzzahlige oder void * Ausdruck wird als Nullzeigerkonstante bezeichnet, und die Standardbibliothek stellt eine Definition dieser Konstante als Makro NULL bereit.

int* p = 0;
double* q = NULL;
**Erklärung:** - Die HTML-Tags und Attribute wurden unverändert beibehalten - Der Code innerhalb der `
`-Tags wurde nicht übersetzt (wie angefordert)
- C++-spezifische Begriffe wie `int`, `double`, `NULL` wurden nicht übersetzt
- Die numerischen Werte `0` und Zeiger-Syntax `*` bleiben unverändert
- Die Formatierung und Struktur des Originalcodes wurde vollständig erhalten

Hinweise

Obwohl ein Überlauf vorzeichenbehafteter Ganzzahlen in jedem arithmetischen Operator undefiniertes Verhalten ist, ist das Überlaufen eines vorzeichenbehafteten Ganzzahltyps in einer Ganzzahlkonvertierung lediglich nicht spezifiziertes Verhalten.

Andererseits ist das Überlaufen eines vorzeichenlosen Ganzzahlwerts in jedem arithmetischen Operator (und bei Ganzzahlkonvertierung) eine wohldefinierte Operation und folgt den Regeln der Modulo-Arithmetik, während das Überlaufen eines vorzeichenlosen Ganzzahlwerts bei einer Gleitkomma-zu-Ganzzahl-Konvertierung undefiniertes Verhalten darstellt: Die Werte des reellen Gleitkommatyps, die in vorzeichenlose Ganzzahlen konvertiert werden können, sind die Werte aus dem offenen Intervall ( -1 , Unnn_MAX + 1 ) .

unsigned int n = -1.0; // undefiniertes Verhalten

Umwandlungen zwischen Zeigern und Ganzzahlen (außer von Zeiger zu _Bool (bis C23) bool (seit C23) und (seit C99) von ganzzahligen konstanten Ausdrücken mit dem Wert null zu Zeigern), zwischen Zeigern auf Objekte (außer wenn einer der Zeiger ein Zeiger auf void ist) und Umwandlungen zwischen Zeigern auf Funktionen (außer wenn die Funktionen kompatible Typen haben) sind niemals implizit und erfordern einen Cast-Operator .

Es gibt keine Konvertierungen (weder implizit noch explizit) zwischen Zeigern auf Funktionen und Zeigern auf Objekte (einschließlich void * ) oder Ganzzahlen.

Referenzen

  • C23-Standard (ISO/IEC 9899:2024):
  • 6.3 Konvertierungen (S: 44-50)
  • C17-Standard (ISO/IEC 9899:2018):
  • 6.3 Konvertierungen (S: 37-41)
  • C11-Standard (ISO/IEC 9899:2011):
  • 6.3 Konvertierungen (S: 50-56)
  • C99 Standard (ISO/IEC 9899:1999):
  • 6.3 Konvertierungen (S: 42-48)
  • C89/C90 Standard (ISO/IEC 9899:1990):
  • 3.2 Konvertierungen

Siehe auch

C++ Dokumentation für Implizite Konvertierungen