Namespaces
Variants
Actions

Implicit conversions

From cppreference.com
< c‎ | language

When an expression is used in the context where a value of a different type is expected, conversion may occur:

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

Conversions take place in the following situations:

Contents

[edit] Conversion as if by assignment

  • In the assignment operator, the value of the right-hand operand is converted to the unqualified type of the left-hand operand.
  • In scalar initialization, the value of the initializer expression is converted to the unqualified type of the object being initialized.
  • In a function-call expression, to a function that has a prototype, the value of each argument expression is converted to the type of the unqualified declared types of the corresponding parameter.
  • In a return statement, the value of the operand of return is converted to an object having the return type of the function.

Note that actual assignment, in addition to the conversion, also removes extra range and precision from floating-point types and prohibits overlaps; those characteristics do not apply to conversion as if by assignment.

[edit] Default argument promotions

In a function call expression when the call is made to

2) a variadic function, where the argument expression is one of the trailing arguments that are matched against the ellipsis parameter.

Each argument of integer type undergoes integer promotion, and each argument of type float is implicitly converted to the type double.

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

Note that float complex and float imaginary are not promoted to double complex and double imaginary in this context.

(since C99)

[edit] Usual arithmetic conversions

The arguments of the following arithmetic operators undergo implicit conversions for the purpose of obtaining the common real type , which is the type in which the calculation is performed:

1) If one operand has decimal floating type, the other operand shall not have standard floating,

complex, or imaginary type.

  • First, if the type of either operand is _Decimal128, the other operand is converted to _Decimal128.
  • Otherwise, if the type of either operand is _Decimal64, the other operand is converted to _Decimal64.
  • Otherwise, if the type of either operand is _Decimal32, the other operand is converted to _Decimal32.
(since C23)
2) Otherwise, if one operand is long double, long double complex, or long double imaginary(since C99), the other operand is implicitly converted as follows:
  • integer or real floating type to long double
(since C99)
3) Otherwise, if one operand is double, double complex, or double imaginary(since C99), the other operand is implicitly converted as follows:
  • integer or real floating type to double
(since C99)
4) Otherwise, if one operand is float, float complex, or float imaginary(since C99), the other operand is implicitly converted as follows:
  • integer type to float (the only real type possible is float, which remains as-is)
(since C99)
5) Otherwise, both operands are integers. Both operands undergo integer promotions; then, after integer promotion, one of the following cases applies:
  • If the types are the same, that type is the common type.
  • Else, the types are different:
    • If the types have the same signedness (both signed or both unsigned), the operand whose type has the lesser conversion rank [1] is implicitly converted[2] to the other type.
    • Else, the operands have different signedness:
      • If the unsigned type has conversion rank greater than or equal to the rank of the signed type, then the operand with the signed type is implicitly converted to the unsigned type.
      • Else, the unsigned type has conversion rank less than the signed type:
        • If the signed type can represent all values of the unsigned type, then the operand with the unsigned type is implicitly converted to the signed type.
        • Else, both operands undergo implicit conversion to the unsigned type counterpart of the signed operand's type.
  1. Refer to integer promotions below for the rules on ranking.
  2. Refer to “integer conversions” under implicit conversion semantics below.
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

The result type is determined as follows:

  • if both operands are complex, the result type is complex;
  • if both operands are imaginary, the result type is imaginary;
  • if both operands are real, the result type is real;
  • if the two floating-point operands have different type domains (complex vs. real, complex vs imaginary, or imaginary vs. real), the result type is complex.
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
(since C99)

As always, the result of a floating-point operator may have greater range and precision than is indicated by its type (see FLT_EVAL_METHOD).

Note: real and imaginary operands are not implicitly converted to complex because doing so would require extra computation, while producing undesirable results in certain cases involving infinities, NaNs and signed zeros. For example, if reals were converted to complex, 2.0×(3.0+i∞) would evaluate as (2.0+i0.0)×(3.0+i∞) ⇒ (2.0×3.0–0.0×∞) + i(2.0×∞+0.0×3.0) ⇒ NaN+i∞ rather than the correct 6.0+i∞. If imaginaries were converted to complex, i2.0×(∞+i3.0) would evaluate as (0.0+i2.0) × (∞+i3.0) ⇒ (0.0×∞ – 2.0×3.0) + i(0.0×3.0 + 2.0×∞) ⇒ NaN + i∞ instead of –6.0 + i∞.

(since C99)

Note: regardless of usual arithmetic conversions, the calculation may always be performed in a narrower type than specified by these rules under the as-if rule.

[edit] Value transformations

[edit] Lvalue conversion

Any lvalue expression of any non-array type, when used in any context other than

undergoes lvalue conversion : the type remains the same, but loses const/volatile/restrict-qualifiers and