Implicit conversions
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:
[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
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:
- binary arithmetic *, /, %, +, -,
- relational operators <, >, <=, >=, ==, !=,
- binary bitwise arithmetic &, ^, |,
- the conditional operator ?:.
|
1) If one operand has decimal floating type, the other operand shall not have standard floating,
complex, or imaginary type.
|
(since C23) |
- integer or real floating type to long double
| (since C99) |
- integer or real floating type to double
| (since C99) |
- integer type to float (the only real type possible is float, which remains as-is)
| (since C99) |
- 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.
- ↑ Refer to integer promotions below for the rules on ranking.
- ↑ 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:
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
- as the operand of the address-of operator (if allowed),
- as the operand of the pre/post increment and decrement operators,
- as the left-hand operand of the member access (dot) operator,
- as the left-hand operand of the assignment and compound assignment operators,
- as the operand of
sizeof,
undergoes lvalue conversion : the type remains the same, but loses const/volatile/restrict-qualifiers and