## 4.1. Conversion of Arithmetic TypesType conversions are always possible between any two arithmetic types
, and the compiler performs them implicitly wherever necessary. The conversion preserves the value of an expression if the new type is capable of representing it. This is not always the case. For example, when you convert a negative value to an unsigned type, or convert a floating-point fraction from type ## 4.1.1. Hierarchy of TypesWhen arithmetic operands have different types, the implicit type conversion is governed by the types' conversion rank . The types are ranked according to the following rules: Any two unsigned integer types have different conversion ranks. If one is wider than the other, then it has a higher rank. Each signed integer type has the same rank as the corresponding unsigned type. The type `char`has the same rank as`signed char`and`unsigned char`.The standard integer types are ranked in the order: _Bool < char < short < int < long < long long
Any standard integer type has a higher rank than an extended integer type of the same width. (Extended integer types are described in the section "Integer Types with Exact Width (C99)" in Chapter 2.) Every enumerated type has the same rank as its corresponding integer type (see "Enumerated Types" in Chapter 2). The floating-point types are ranked in the following order: float < double < long double
The lowest-ranked floating-point type, `float`, has a higher rank than any integer type.Every complex floating-point type has the same rank as the type of its real and imaginary parts.
## 4.1.2. Integer PromotionIn any expression, you can always use a value whose type ranks lower than Integer promotion always preserves the value of the operand. Some examples: char c = '?'; unsigned short var = 100; if ( c < 'A' ) // The character constant 'A' has type int: the value // of c is implicitly promoted to int for the // comparison. var = var + 1; // Before the addition, the value of var is promoted // to int or unsigned int. In the last of these statements, the compiler promotes the first addend, the value of ## 4.1.3. Usual Arithmetic ConversionsThe The usual arithmetic conversions are performed implicitly for the following operators: Arithmetic operators with two operands: `*`,`/`,`%`,`+`, and`-`Relational and equality operators: `<`,`<=`,`>`,`>=`,`==`, and`!=`The bitwise operators, `&`,`|`, and`^`The conditional operator, `?:`(for the second and third operands)
With the exception of the relational and equality operators, the common real type obtained by the usual arithmetic conversions is generally the type of the result. However, if one or more of the operands has a complex floating-point type, then the result also has a complex floating-point type. The usual arithmetic conversions are applied as follows: If either operand has a floating-point type, then the operand with the lower conversion rank is converted to a type with the same rank as the other operand. Real types are converted only to real types, however, and complex types only to complex. In other words, if either operand has a complex floating-point type, the usual arithmetic conversion matches only the real type on which the actual type of the operand is based. Some examples: #include <complex.h> // ... short n = -10; double x = 0.5, y = 0.0; float _Complex f_z = 2.0F + 3.0F * I; double _Complex d_z = 0.0; y = n * x; // The value of n is converted to type double. d_z = f_z + x; // Only the value of f_z is converted to // double _Complex. // The result of the operation also has type // double _Complex. f_z = f_z / 3; // The constant value 3 is converted to float. d_z = d_z - f_z; // The value of f_z is converted to the type // double _Complex.
If both operands are integers, integer promotion is first performed on both operands. If after integer promotion the operands still have different types, conversion continues as follows: If one operand has an unsigned type whose conversion rank is at least as high as that of the other operand's type, then the other operand is converted to type*T*.*T*Otherwise, one operand has a signed type whose conversion rank is higher than that of the other operand's type. The other operand is converted to type*T*only if type*T*is capable of representing all values of its previous type. If not, then both operands are converted to the unsigned type that corresponds to the signed type*T*.*T*
The following lines of code contain some examples: int i = -1; unsigned int limit = 200U; long n = 30L; if ( i < limit ) x = limit * n; In this example, to evaluate the comparison in the In the last line of the example, the value of The usual arithmetic conversions preserve the operand's value, except in the following cases: When an integer of great magnitude is converted to a floating-point type, the target type's precision may not be sufficient to represent the number exactly. Negative values are outside the value range of unsigned types.
In these two cases, values that exceed the range or precision of the target type are converted as described under "The Results of Arithmetic Type Conversions," later in this chapter. ## 4.1.4. Other Implicit Type ConversionsThe compiler also automatically converts arithmetic values in the following cases: In assignments and initializations, the value of the right operand is always converted to the type of the left operand. In function calls, the arguments are converted to the types of the corresponding parameters. If the parameters have not been declared, then the default argument promotions are applied: integer promotion is performed on integer arguments, and arguments of type `float`are promoted to`double`.In `return`statements, the value of the`return`expression is converted to the function's return type.
In a compound assignment, such as #include <math.h> // Declares the function double sqrt( double ). int i = 7; float x = 0.5; // The constant value is converted from double to float. i = x; // The value of x is converted from float to int. x += 2.5; // Before the addition, the value of x is converted to // double. Afterward, the sum is converted to float for // assignment to x. x = sqrt( i ); // Calculate the square root of i: // The argument is converted from int to double; the return // value is converted from double to float for assignment to x. long my_func( ) { /* ... */ return 0; // The constant 0 is converted to long, the function's return // type. } ## 4.1.5. The Results of Arithmetic Type ConversionsBecause the different types have different purposes, representational characteristics, and limitations, converting a value from one type to another often involves the application of special rules to deal with such peculiarities. In general, the exact result of a type conversion depends primarily on the characteristics of the target type. ## 4.1.5.1. Conversions to _BoolAny value of any scalar type can be converted to ## 4.1.5.2. Conversions to unsigned integer types other than _BoolInteger values are always preserved if they are within the range of the new unsigned typein other words, if they are between 0 and For values outside the new unsigned type's range, the value after conversion is the value obtained by adding or subtracting ( #include <limits.h> // Defines the macros USHRT_MAX, UINT_MAX, etc. unsigned short n = 1000; // The value 1000 is within the range of unsigned // short; n = -1; // the value -1 must be converted. To adjust a signed value of -1 to the variable's unsigned type, the program implicitly adds For positive integer values, subtracting ( #include <limits.h> // Defines the macros USHRT_MAX, UINT_MAX, etc. unsigned short n = 0; n = 0xFEDCBA; // The value is beyond the range of unsigned // short. If To convert a real floating-point number to an unsigned or signed integer type, the compiler discards the fractional part. If the remaining integer portion is outside the range of the new type, the result of the conversion is undefined. Example: double x = 2.9; unsigned long n = x; // The fractional part of x is simply lost. unsigned long m = round(x); // If x is non-negative, this has the // same effect as m = x + 0.5; In the initialization of When a complex number is converted to an unsigned integer type, the imaginary part is first discarded. Then the resulting floating-point value is converted as described previously. Example: #include <limits.h> // Defines macros such as UINT_MAX. #include <complex.h> // Defines macros such as the imaginary // constant I. unsigned int n = 0; float _Complex z = -1.7 + 2.0 * I; n = z; // In this case, the effect is the same as // n = -1; // The resulting value of n is UINT_MAX. The imaginary part of ## 4.1.5.3. Conversions to signed integer typesThe problem of exceeding the target type's value range can also occur when a value is converted from an integer type, whether signed or unsigned, to a different, signed integer type; for example, when a value is converted from the type Most compilers discard the highest bits of the original value's binary representation and interpret the lowest bits according to the new type. As the following example illustrates, under this conversion strategy the existing bit pattern of an #include <limits.h> // Defines macros such as UINT_MAX int i = UINT_MAX; // Result: i = -1 (in two's complement // representation) However, depending on the compiler, such a conversion attempt may also result in a signal being raised to inform the program of the value range overflow. When a real or complex floating-point number is converted to a signed integer type, the same rules apply as for conversion to an unsigned integer type, as described in the previous section. ## 4.1.5.4. Conversions to real floating-point typesNot all integer values can be exactly represented in floating-point types. For example, although the value range of the type long l_var = 123456789L; float f_var = l_var; // Implicitly converts long value to float. printf("The rounding error (f_var - l_var) is %f\n", f_var - l_var); Remember that the subtraction in this example, like all floating-point arithmetic, is performed with at least The rounding error (f_var - l_var;) is 3.000000 Any value in a floating-point type can be represented exactly in another floating-point type of greater precision. Thus when a When a complex number is converted to a real floating-point type, the imaginary part is simply discarded, and the result is the complex number's real part, which may have to be further converted to the target type as described in this section. ## 4.1.5.5. Conversions to complex floating-point typesWhen an integer or a real floating-point number is converted to a complex type, the real part of the result is obtained by converting the value to the corresponding real floating-point type as described in the previous section. The imaginary part is zero. When a complex number is converted to a different complex type, the real and imaginary parts are converted separately according to the rules for real floating-point types. #include <complex.h> // Defines macros such as the imaginary // constant I double _Complex dz = 2; float _Complex fz = dz + I; In the first of these two initializations, the integer constant 2 is implicitly converted to In the initialization of |