Namensräume
Varianten
Aktionen

Implizite Konvertierungen

Von cppreference.com
< c‎ | Sprache

Wenn ein Ausdruck im Kontext verwendet wird, in dem ein Wert eines anderen Typs erwartet wird, kann eine Konvertierung stattfinden.

int n = 1L; // expression 1L has type long, int is expected
n = 2.1; // expression 2.1 has type double, int is expected
char *p = malloc(10); // expression malloc(10) has type void*, char* is expected

Konvertierungen finden in folgenden Situationen statt:

Inhalt

[bearbeiten] Konvertierung wie durch Zuweisung

  • Im Zuweisungsoperator wird der Wert des rechten Operanden in den unqualifieden Typ des linken Operanden konvertiert.
  • Bei der Skalarinitialisierung wird der Wert des Initialisierungsausdrucks in den unqualifieden Typ des zu initialisierenden Objekts konvertiert.
  • In einem Funktionsaufrufausdruck wird der Wert jedes Argumentausdrucks in den Typ der unqualified deklarierten Typen des entsprechenden Parameters konvertiert, wenn der Aufruf an eine Funktion mit Prototyp erfolgt.
  • 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 den zusätzlichen Bereich und die Präzision von Gleitkommatypen entfernt und Überlappungen verbietet; diese Eigenschaften gelten nicht für die Konvertierung wie durch Zuweisung.

[bearbeiten] Standard-Argument-Promotions

Bei einem Funktionsaufrufausdruck, wenn der Aufruf erfolgt an

1) eine Funktion ohne Prototyp (bis C23)
2) eine variadische Funktion, wobei der Argumentausdruck eines der nachfolgenden Argumente ist, die dem Ellipsenparameter zugeordnet werden.

Jedes Argument vom Integer-Typ unterliegt einer Integer-Promotion (siehe unten), und jedes Argument vom Typ float wird implizit in den Typ double konvertiert.

int add_nums(int count, ...);
int sum = add_nums(2, 'c', true); // add_nums is called with three ints: (2, 99, 1)

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

(seit C99)

[bearbeiten] Übliche arithmetische Konvertierungen

Die Operanden der folgenden arithmetischen Operatoren unterliegen impliziten Konvertierungen zur Ermittlung des gemeinsamen Realtyps, in dem die Berechnung durchgeführt wird:

1) Wenn ein Operand vom Typ "decimal floating type" ist, darf der andere Operand nicht von einem Standard-Floating-, komplexen oder imaginären Typ sein.

komplexen oder imaginären Typ sein.

  • Wenn der Typ eines Operanden _Decimal128 ist, wird der andere Operand zu _Decimal128 konvertiert.
  • Wenn andernfalls der Typ eines Operanden _Decimal64 ist, wird der andere Operand zu _Decimal64 konvertiert.
  • Wenn andernfalls der Typ eines Operanden _Decimal32 ist, wird der andere Operand zu _Decimal32 konvertiert.
(seit C23)
2) Wenn andernfalls ein Operand long double, long double complex oder long double imaginary (seit C99) ist, wird der andere Operand implizit wie folgt konvertiert:
  • Integer- oder Real-Floating-Typ zu long double
(seit C99)
3) Wenn andernfalls ein Operand double, double complex oder double imaginary (seit C99) ist, wird der andere Operand implizit wie folgt konvertiert:
  • Integer- oder Real-Floating-Typ zu double
(seit C99)
4) Wenn andernfalls ein Operand float, float complex oder float imaginary (seit C99) ist, wird der andere Operand implizit wie folgt konvertiert:
  • Integer-Typ zu float (der einzige mögliche Realtyp ist float, der unverändert bleibt)
(seit C99)
5) Wenn andernfalls beide Operanden Integer sind. Beide Operanden unterliegen einer Integer-Promotion (siehe unten); danach gilt, nach der Integer-Promotion, einer der folgenden Fälle:
  • Wenn die Typen gleich sind, ist dieser Typ der gemeinsame Typ.
  • Wenn die Typen unterschiedlich sind.
    • Wenn die Typen die gleiche Vorzeichenigkeit haben (beide vorzeichenbehaftet oder beide vorzeichenlos), wird der Operand, dessen Typ den geringeren Konvertierungsrang1 hat, implizit2 in den anderen Typ konvertiert.
    • Wenn andernfalls die Operanden unterschiedliche Vorzeichenigkeit haben.
      • Wenn der vorzeichenlose Typ einen Konvertierungsrang hat, der größer oder gleich dem Rang des vorzeichenbehafteten Typs ist, dann wird der Operand mit dem vorzeichenbehafteten Typ in den vorzeichenlosen Typ implizit konvertiert.
      • Wenn andernfalls der vorzeichenlose Typ einen geringeren Konvertierungsrang als der vorzeichenbehaftete Typ hat.
        • 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.
        • Wenn andernfalls beide Operanden einer impliziten Konvertierung in den vorzeichenlosen Gegenstücktyp des vorzeichenbehafteten Operanden unterliegen.

1. Informationen zu den Regeln für die Rangordnung finden Sie unter "Integer-Promotions" unten.
2. Informationen zu den "Integer-Konvertierungen" unter "Semantik impliziter Konvertierungen" finden Sie unten.
1.f + 20000001; // int is converted to float, giving 20000000.00
                // addition and then rounding to float gives 20000000.00
 
(char)'a' + 1L; // first, char 'a', which is 97, is promoted to int
                // different types: int and long
                // same signedness: both signed
                // different rank: long is of greater rank than int
                // therefore, int 97 is converted to long 97
                // the result is 97 + 1 = 98 of type signed long
 
2u - 10; // different types: unsigned int and signed int
         // different signedness
         // same rank
         // therefore, signed int 10 is converted to unsigned int 10
         // since the arithmetic operation is performed for unsigned integers
         // (see "Arithmetic operators" topic), the calculation performed is (2 - 10)
         // modulo (2 raised to n), where n is the number of value bits of unsigned int
         // if unsigned int is 32-bit long and there is no padding bits in its object
         // representation, then the result is (-8) modulo (2 raised to 32) = 4294967288
         // of type unsigned int
 
5UL - 2ULL; // different types: unsigned long and unsigned long long
            // same signedness
            // different rank: rank of unsigned long long is greater
            // therefore, unsigned long 5 is converted to unsigned long long 5
            // since the arithmetic operation is performed for unsigned integers
            // (see "Arithmetic operators" topic),
            // if unsigned long long is 64-bit long, then
            // the result is (5 - 2) modulo (2 raised to 64) = 3 of type
            // unsigned long long
 
0UL - 1LL; // different types: unsigned long and signed long long
           // different signedness
           // different rank: rank of signed long long is greater.
           // if ULONG_MAX > LLONG_MAX, then signed long long cannot represent all
           // unsigned long therefore, this is the last case: both operands are converted
           // to unsigned long long unsigned long 0 is converted to unsigned long long 0
           // long long 1 is converted to unsigned long long 1 since the arithmetic
           // operation is performed for unsigned integers
           // (see "Arithmetic operators" topic),
           // if unsigned long long is 64-bit long, then  
           // the calculation is (0 - 1) modulo (2 raised to 64)
           // thus, the result is 18446744073709551615 (ULLONG_MAX) of type
           // 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 Gleitkommaoperanden unterschiedliche Typdomänen (komplex vs. reell, komplex vs. imaginär oder imaginär vs. reell) haben, 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 Gleitkommaoperators einen größeren Bereich und eine höhere Präzision aufweisen, als durch seinen Typ angezeigt wird (siehe FLT_EVAL_METHOD).

Hinweis: Reelle und imaginäre Operanden werden nicht implizit in komplexe konvertiert, da dies zusätzliche Berechnungen erfordern und in bestimmten Fällen mit Unendlichkeiten, NaNs und vorzeichenbehafteten Nullen unerwünschte Ergebnisse liefern würde. Zum Beispiel würde 2.0×(3.0+i∞) als (2.0+i0.0)×(3.0+i∞) ⇒ (2.0×3.0–0.0×∞) + i(2.0×∞+0.0×3.0) ⇒ NaN+i∞ ausgewertet, anstatt des korrekten 6.0+i∞. Wenn Imaginäre 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∞ statt –6.0 + i∞ ausgewertet.

(seit C99)

Hinweis: Unabhängig von den üblichen arithmetischen Konvertierungen kann die Berechnung gemäß der "as-if"-Regel stets in einem schmaleren Typ als den nach diesen Regeln angegebenen durchgeführt werden.

[bearbeiten] Werttransformationen

[bearbeiten] Lvalue-Konvertierung

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

verwendet wird, unterliegt einer lvalue-Konvertierung: Der Typ bleibt gleich, verliert jedoch Const-/Volatile-/Restrict-Qualifizierer und atomare Eigenschaften, falls vorhanden. Der Wert bleibt gleich, verliert jedoch seine lvalue-Eigenschaften (die Adresse darf nicht mehr genommen werden).

Wenn das lvalue einen unvollständigen Typ hat, ist das Verhalten undefiniert.

Wenn das lvalue ein Objekt mit automatischer Speicherdauer bezeichnet, dessen Adresse nie genommen wurde und wenn dieses Objekt uninitialisiert war (nicht mit einem Initialisierer deklariert und vor der Verwendung keine Zuweisung dazu erfolgt ist), ist das Verhalten undefiniert.

Diese Konvertierung modelliert das Laden des Wertes des Objekts aus seinem Speicherort.

volatile int n = 1;
int x = n;            // lvalue conversion on n reads the value of n
volatile int* p = &n; // no lvalue conversion: does not read the value of n

[bearbeiten] Array-zu-Zeiger-Konvertierung

Jeder lvalue-Ausdruck vom Array-Typ, wenn er in einem anderen Kontext als

verwendet wird, unterliegt einer Konvertierung in den Nicht-lvalue-Zeiger auf sein erstes Element.

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

int a[3], b[3][4];
int* p = a;      // conversion to &a[0]
int (*q)[4] = b; // conversion to &b[0]

[bearbeiten] Funktion-zu-Zeiger-Konvertierung

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

verwendet wird, unterliegt einer Konvertierung in den Nicht-lvalue-Zeiger auf die durch den Ausdruck bezeichnete Funktion.

int f(int);
int (*p)(int) = f; // conversion to &f
(***p)(1); // repeated dereference to f and conversion back to &f

[bearbeiten] Semantik impliziter Konvertierungen

Die implizite Konvertierung, ob wie durch Zuweisung oder übliche arithmetische Konvertierung, besteht aus zwei Stufen:

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

[bearbeiten] Kompatible Typen

Die Konvertierung eines Wertes eines beliebigen Typs in einen beliebigen kompatiblen Typ ist immer eine No-Op und ändert die Darstellung nicht.

uint8_t (*a)[10];         // if uint8_t is a typedef to unsigned char
unsigned char (*b)[] = a; // then these pointer types are compatible

[bearbeiten] Integer-Promotions

Die Integer-Promotion ist die implizite Konvertierung eines Wertes eines beliebigen Integer-Typs mit einem Rang kleiner oder gleich dem Rang von int oder eines Bitfeldes 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 Bitfeldes) darstellen kann, wird der Wert in den Typ int konvertiert. Andernfalls wird der Wert in unsigned int konvertiert.

Der Wert eines Bitfeldes eines bitpräzisen Integer-Typs wird in den entsprechenden bitpräzisen Integer-Typ konvertiert. Andernfalls sind bitpräzise Integer-Typen von den Regeln für Integer-Promotions ausgenommen.

(seit C23)

Integer-Promotions erhalten den Wert, einschließlich des Vorzeichens.

int main(void)
{
    void f(); // old-style function declaration
              // since C23, void f(...) has the same behavior wrt promotions
    char x = 'a'; // integer conversion from int to char
    f(x); // integer promotion from char back to int
}
 
void f(x) int x; {} // the function expects int

Rang oben ist eine Eigenschaft jedes Integer-Typs und ist wie folgt definiert:

1) Die Ränge aller vorzeichenbehafteten Integer-Typen 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 Integer-Typen entsprechen den Rängen der entsprechenden vorzeichenlosen Integer-Typen.
3) Der Rang eines beliebigen Standard-Integer-Typs ist größer als der Rang eines beliebigen erweiterten Integer-Typs oder bitpräzisen Integer-Typs(seit C23) gleicher 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) Der Rang von char entspricht dem Rang von signed char und dem Rang von unsigned char.
5) Der Rang von _Bool(bis C23)bool(seit C23) ist geringer als der Rang jedes anderen Standard-Integer-Typs.
6) Der Rang eines beliebigen Aufzählungstyps entspricht dem Rang seines kompatiblen Integer-Typs.
7) Die Rangordnung 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 vorzeichenbehafteten bitpräzisen Integer-Typs muss größer sein als der Rang eines Standard-Integer-Typs mit geringerer Breite oder eines bitpräzisen Integer-Typs mit geringerer Breite.
9) Der Rang eines beliebigen bitpräzisen Integer-Typs im Verhältnis zu einem erweiterten Integer-Typ gleicher Breite ist implementierungsabhängig.
(seit C23)
10) Jegliche Aspekte der relativen Rangordnung von erweiterten Integer-Typen, die nicht oben abgedeckt sind, sind implementierungsabhängig.

Hinweis: Integer-Promotions werden nur angewendet

  • als Teil von üblichen arithmetischen Konvertierungen (siehe oben)
  • als Teil von Standard-Argument-Promotions (siehe oben)
  • auf den Operanden der unären arithmetischen Operatoren + und -
  • auf den Operanden des unären bitweisen Operators ~
  • auf beide Operanden der Verschiebungsoperatoren << und >>

Boolesche Konvertierung

Ein Wert eines beliebigen Skalar-Typs kann implizit in _Bool(bis C23)bool(seit C23) konvertiert werden. Werte, die mit einem ganzzahligen konstanten Ausdruck mit dem Wert null übereinstimmen(bis C23)null (für arithmetische Typen), null (für Zeigertypen) oder einen Typ nullptr_t haben(seit C23) sind, werden zu 0(bis C23)false(seit C23) konvertiert, alle anderen Werte werden zu 1(bis C23)true(seit C23) konvertiert.

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)

[bearbeiten] Integer-Konvertierungen

Ein Wert eines beliebigen Integer-Typs kann implizit in jeden anderen Integer-Typ konvertiert werden. Außer wo oben durch Promotions und boolesche Konvertierungen abgedeckt, gelten die Regeln:

  • Wenn der Zieltyp den Wert darstellen kann, bleibt der Wert unverändert.
  • Wenn der Zieltyp vorzeichenlos ist, wird 2b
    , wobei b die Anzahl der Wertbits im Zieltyp ist, wiederholt vom Quellwert subtrahiert oder hinzugefügt, bis das Ergebnis in den Zieltyp passt. Mit anderen Worten, vorzeichenlose Integer implementieren Modulo-Arithmetik.
  • Wenn der Zieltyp vorzeichenbehaftet ist, ist das Verhalten implementierungsabhängig (was die Auslösung eines Signals einschließen kann).
char x = 'a'; // int -> char, result unchanged
unsigned char n = -123456; // target is unsigned, result is 192 (that is, -123456+483*256)
signed char m = 123456;    // target is signed, result is implementation-defined
assert(sizeof(int) > -1);  // assert fails:
                           // operator > requests conversion of -1 to size_t,
                           // target is unsigned, result is SIZE_MAX

[bearbeiten] Real-Floating-Integer-Konvertierungen

Ein endlicher Wert eines beliebigen reellen Gleitkommatyps kann implizit in jeden Integer-Typ konvertiert werden. Außer wo oben durch boolesche Konvertierung abgedeckt, gelten die Regeln:

  • Der Nachkommateil wird verworfen (gegen Null abgeschnitten).
  • Wenn der resultierende Wert vom Zieltyp dargestellt werden kann, wird dieser Wert verwendet.
  • Andernfalls ist das Verhalten undefiniert.
int n = 3.14; // n == 3
int x = 1e10; // undefined behavior for 32-bit int

Ein Wert eines beliebigen Integer-Typs kann implizit in jeden reellen Gleitkommatyp konvertiert werden.

  • Wenn der Wert exakt vom Zieltyp dargestellt werden kann, bleibt er unverändert.
  • Wenn der Wert dargestellt werden kann, aber nicht exakt, ist das Ergebnis eine implementierungsabhängige Wahl zwischen dem nächsthöheren oder nächstniedrigeren Wert (obwohl bei Unterstützung von IEEE-Arithmetik die Rundung zum Nächsten erfolgt). 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 Unterstützung von IEEE-Arithmetik FE_INVALID ausgelöst wird und der Ergebniswert nicht spezifiziert ist.

Das Ergebnis dieser Konvertierung kann einen größeren Bereich und eine höhere Präzision aufweisen, als sein Zieltyp angibt (siehe FLT_EVAL_METHOD).

Wenn Steuerung über FE_INEXACT bei Gleitkomma-zu-Integer-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; // undefined behavior

[bearbeiten] Real-Floating-Point-Konvertierungen

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

  • Wenn der Wert exakt vom 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 (d. h. die Rundungsrichtung ist implementierungsabhängig), obwohl bei Unterstützung von IEEE-Arithmetik die Rundung zum Nächsten erfolgt.
  • Wenn der Wert nicht dargestellt werden kann, ist das Verhalten undefiniert.

Das Ergebnis dieser Konvertierung kann einen größeren Bereich und eine höhere Präzision aufweisen, als sein 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; // undefined

Komplexe Typkonvertierungen

Ein Wert eines beliebigen komplexen Typs kann implizit in jeden anderen komplexen Typ konvertiert werden. Der Realteil und der Imaginärteil folgen einzeln den Konvertierungsregeln für reelle Gleitkommatypen.

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

Imaginäre Typkonvertierungen

Ein Wert eines beliebigen imaginären Typs kann implizit in jeden anderen imaginären Typ konvertiert werden. Der Imaginärteil folgt den Konvertierungsregeln für reelle Gleitkommatypen.

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

Real-Komplexe Konvertierungen

Ein Wert eines beliebigen reellen Gleitkommatyps kann implizit in jeden komplexen Typ konvertiert werden.

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

Ein Wert eines beliebigen komplexen Typs kann implizit in jeden reellen Gleitkommatyp konvertiert werden.

  • Der Realteil wird gemäß den Regeln für reelle Gleitkommatypen konvertiert.
  • Der Imaginärteil wird verworfen.

Hinweis: Bei komplex-zu-reeller Konvertierung wird ein NaN im Imaginärteil nicht auf das reelle Ergebnis übertragen.

double complex z = 0.5 + 3*I;
float f = z;  // the imaginary part is discarded, f is set to 0.5
z = f;        // sets z to 0.5 + 0*I

Real-Imaginäre Konvertierungen

Ein Wert eines beliebigen imaginären Typs kann implizit in jeden reellen Typ (Integer oder Gleitkomma) 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 Regeln für boolesche Konvertierungen gelten.

Ein Wert eines beliebigen 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;  // Boolean conversion: sets b to true 
float f = z; // Real-imaginary conversion: sets f to 0.0 
z = 3.14;    // Imaginary-real conversion: sets z to 0*_Imaginary_I

Komplex-Imaginäre Konvertierungen

Ein Wert eines beliebigen 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 eines beliebigen 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); // the complex result -3.0+0i loses real part
                                // sets z to 0*_Imaginary_I
(seit C99)

[bearbeiten] Zeigerkonvertierungen

Ein Zeiger auf void kann implizit in jeden Zeiger auf einen Objekttyp konvertiert und von diesem zurückkonvertiert werden, mit den folgenden Semantiken:

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

Ein Zeiger auf einen nicht qualifizierten Typ darf implizit in die qualifizierte Version dieses Typs konvertiert werden (mit anderen Worten, const, volatile und restrict Qualifikatoren können hinzugefügt werden). Der ursprüngliche Zeiger und das Ergebnis vergleichen sich gleich.

int n;
const int* p = &n; // &n has type int*

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

int* p = 0;
double* q = NULL;

[bearbeiten] Hinweise

Obwohl ein Überlauf vorzeichenbehafteter Ganzzahlen bei jedem arithmetischen Operator undefiniertes Verhalten darstellt, ist der Überlauf eines vorzeichenbehafteten Ganzzahltyps bei einer Ganzzahlkonvertierung lediglich nicht spezifiziertes Verhalten.

Andererseits, obwohl ein Überlauf vorzeichenloser Ganzzahlen bei jedem arithmetischen Operator (und bei Ganzzahlkonvertierungen) eine wohldefinierte Operation ist und den Regeln der Modulo-Arithmetik folgt, ist ein Überlauf vorzeichenloser Ganzzahlen bei einer Konvertierung von Gleitkommazahlen zu Ganzzahlen undefiniertes Verhalten: Die Werte vom Typ Real-Gleitkommazahl, die in vorzeichenlose Ganzzahlen konvertiert werden können, sind die Werte aus dem offenen Intervall (-1; Unnn_MAX+1).

unsigned int n = -1.0; // undefined behavior

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

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

[bearbeiten] Referenzen

  • C23-Standard (ISO/IEC 9899:2024)
  • 6.3 Konvertierungen (S. TBD)
  • 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

[bearbeiten] Siehe auch

C++ Dokumentation für Implizite Konvertierungen