1. Integer Promotion
In an expression, any place where an int or unsigned int type can be used to do the right value can also use a signed or non  the char, short, and Bitfield symbols. If the value range of the original type can be represented by an int, its value is promoted to int, or, if it is not, promoted to unsigned int, which is called an integer Promotion. Doingan integer promotion only affects the values of the above types and has no effect on other types. C99 specifies that the integer promotion applies to
The following situations:
1, if the formal parameter type of a function is unknown, for example, using the old style Cstyle function declaration , or there is ... in the parameter list of the function, then you do an integer to the corresponding argument when you call the function Promotion, in addition, the corresponding argument, if it is a float type, is also promoted to double type, which is called the default Argument Promotion. We know that the list of parameters in printf has ..., except for the first parameter, the type of the other formal parameter is unknown, so when we call printf ("%c", ' a '), ' a ' is actually promoted to int type before being passed to The printf.
2. Type conversion in arithmetic operations. The operands of two arithmetic types do arithmetic operations, such as a * b, if the type of the operands on both sides is different, the compiler will do the type change automatically, so that the two sides of the same type after the operation, which is called usual arithmetic Conversion, One step in the conversion process is an integer Promotion, let's take an example to understand this step, as for usual arithmetic conversion's complete rules will be explained in detail below.
unsigned char c1 = 255, C2 = 2;
int n = c1 + C2;
the process of evaluating the expression C1 + C2 is to first promote the C1 and C2 to the int type and then add the value of the unsigned char is 0~255, it can be represented by int, so it does not need to be promoted to unsigned int), and the value of the entire expression is of type int, and the final result is 257. Without this process of ascension, the C1 + C2 will overflow, and the final result should be 1.
Obviously, +*/% these arithmetic operations as well as the > < >= <= = = =These comparison operations need to be usual arithmetic Conversion, because both sides of the operands are required to be of the same type, and what operations also need to be usual arithmetic Where's conversion? We will make a summary in the next chapter.
3, monocular operator + + 、、 ~ Only one operand, shift operator <<, >> operand types on both sides do not require consistency, because These operations do not need to do usual arithmetic Conversion, but also need to do an integer Promotion.
2. Usual Arithmetic Conversion
Now explain in detail the rules of usual arithmetic conversion:
1. If the type of one side is long double, the other side is also converted to a long double.
2. Otherwise, if one side of the type is double, the other side is also converted to double.
3. Otherwise, if one side is of type float, turn the other side into float.
4. Otherwise, both sides should be of integer type, first an integer Promotion for A and B as per the rules in the previous section , and then if the type is still different, you need to continue the conversion. First, specify the conversion level of char, short, int, long, long long (Integer Conversion rank) a higher, the same type of signed and unsigned numbers with the same rank, Then there are the following conversion rules:
A. If both sides are signed, or if both are unsigned, the lower rank type is converted to the higher rank type. For example, unsigned int and unsigned long do arithmetic operations and all turn to unsigned long.
B. Otherwise, if one side is an unsigned number on the other side is a signed number, the unsigned number of rank is not lower than the signed number of rank, then the signed number is converted to the other side of the unsigned type. For example unsigned long and int do arithmetic operations are turned into unsigned long,unsigned long and long do arithmetic operations are also turned into unsigned
Long
c. The rest of the situation is that one side is an unsigned number on the other side is a signed number, and the unsigned number of rank is lower than the signed number of rank. Then there are two cases, if the signed number type can cover the range of the unsigned number type, then the unsigned number is converted to the other side of the signed type. For example, follow the LP64 platform
The unsigned int and long are converted to long when doing arithmetic operations.
d. Otherwise, that is, the symbol number type is not sufficient to cover the range of values for this unsigned number type, then both sides are converted to the unsigned type of the higher rank of the two. For example, on platforms that follow ILP32, unsigned int and long are all converted to unsigned long when doing arithmetic operations. It is very complicated to see the conversion rules for signed and unsigned integers, although this is clearly defined and does not fall into the dark corner , but for the readability of the program, you should not rely on these rules to write code. I'm not talking about these rules for you , but to make it easier for you to analyze the cause of the error when it goes wrong, so these rules don't need to be remembered, but you know that there is something that can be found when you use it.
3. Conversion of types generated by assignment
If the type is different on both sides of the equals sign at assignment or initialization, the compiler converts the type to the right of the equal sign to the left side of the equals sign. type to be assigned again. For example, int c = 3.14, the compiler will convert the double type of the right to the int type and then to the variable C. We know that the procedure of a function call is equivalent to defining a parameter and initializing it with an argument, and the process of returning the function is to define a temporary variable and initialize it with a return expression, so that the type conversion generated by the assignment is also appropriate used in both cases. For example, the prototype of a function is an int foo (int, int), then calling Foo (3.1, 4.2) will automatically convert the arguments of the two double type to the int type, and if there is a return statement 1.2 in the function definition, return a return value of 1.2 is automatically converted to type int and returned. type conversions that occur during function calls and returns are often overlooked because function prototypes and function calls are not written together. For example char C = GetChar (), see this sentence, often assume that the return value of GetChar is a char type , and in fact, the return value of GetChar is an int, so that the assignment will cause a type conversion, we will later in detail Use this function to pay attention to the problem.
4. Forcing type conversions
The above three cases are known as implicit type conversions (implicit Conversion, or coercion), and the compiler, based on its self  your own set of rules automatically converts one type to another. In addition to this, programmers can also use the type conversion operator (Cast Operator) to specify what type of value to convert to, which is called an explicit type conversion (Explicit Conversion) or coercion type conversion (type Cast). For example, the calculation expression (double) 3 + I, first convert the integer 3 to double type 3.0, and then add to the integer variable i, then apply usual arithmetic conversion rule, the first First I also turn into a double type, and then add the two, and finally the entire expression value is double. Here (double) is a type conversion operator, which consists of a type name plus () parentheses, followed by 3 is the operand of the operator.
3. Conversion of types generated by assignment
If the type is different on both sides of the equals sign at assignment or initialization, the compiler converts the type on the right side of the equal sign to the type to the left of the equal sign and then assigns the value. For example, int c = 3.14, the compiler will convert the double type of the right to the int type and then to the variable C. We know that the procedure of a function call is equivalent to defining a parameter and initializing it with an argument, and the function returns a procedure that defines a temporary variable and initializes it with a return expression, so that the type conversion produced by the assignment also applies to both cases. For example, the prototype of a function is an int foo (int, int), then calling Foo (3.1, 4.2) will automatically convert the arguments of the two double type to the int type, if the function definition has a return statement of 1.2; The return value of 1.2 is automatically converted to type int and returned. Type conversions that occur during function calls and returns are often overlooked because function prototypes and function calls are not written together. For example char C = GetChar (), see this sentence, often assume that the return value of GetChar is a char type, and in fact, the return value of GetChar is an int, so that the assignment will cause a type conversion, we will explain in detail the use of this function to pay attention to the problem. 3.4. Coercion type conversion The above three cases are known as implicit type conversions (implicit Conversion, or coercion), and the compiler automatically converts one type to another based on its own set of rules. In addition to this, programmers can also use the type conversion operator (cast Operator) to specify what type of value to convert to, which is called an explicit type conversion (Explicit Conversion) or coercion type cast. For example, the calculation expression (double) 3 + I, first cast the integer 3 into a double type 3.0, and then add to the integer variable i, then apply usual arithmetic conversion rule, first I also turn into a double, and then the two add, The last value of the entire expression is also double type. Here (double) is a type conversion operator, which consists of a type name plus () parentheses, followed by 3 is the operand of the operator.
3. Conversion of types generated by assignment
If the type is different on both sides of the equals sign at assignment or initialization, the compiler converts the type on the right side of the equal sign to the type to the left of the equal sign and then assigns the value. For example, int c = 3.14, the compiler will convert the double type of the right to the int type and then to the variable C. We know that the procedure of a function call is equivalent to defining a parameter and initializing it with an argument, and the function returns a procedure that defines a temporary variable and initializes it with a return expression, so that the type conversion produced by the assignment also applies to both cases. For example, the prototype of a function is an int foo (int, int), then calling Foo (3.1, 4.2) will automatically convert the arguments of the two double type to the int type, if the function definition has a return statement of 1.2; The return value of 1.2 is automatically converted to type int and returned. Type conversions that occur during function calls and returns are often overlooked because function prototypes and function calls are not written together. For example char C = GetChar (), see this sentence, often assume that the return value of GetChar is a char type, and in fact, the return value of GetChar is an int, so that the assignment will cause a type conversion, we will explain in detail the use of this function to pay attention to the problem. 3.4. Coercion type conversion The above three cases are known as implicit type conversions (implicit Conversion, or coercion), and the compiler automatically converts one type to another based on its own set of rules. In addition, programmers can specify what type of value to convert to by using the type conversion operator (cast Operator), which is called an explicit type conversion (Explicit
Conversion) or coercion type cast. For example, the calculation expression (double) 3 + I, first cast the integer 3 into a double type 3.0, and then add to the integer variable i, then apply usual arithmetic conversion rule, first I also turn into a double, and then the two add, The last value of the entire expression is also double type. Here (double) is a type conversion operator, which consists of a type name plus () parentheses, followed by 3 is the operand of the operator.
5. How the compiler handles type conversions
The sections above describe which situations produce type conversions, and what types should be turned into each case, and how the conversion between the two types is specifically done is the content of this section. The main content of this section is derived from [standard C]. To convert between the two types, the result will depend on the precision of both types. How do you define the type of precision? We have three kinds of situations to discuss:
1. The signed integer type with a precision of n should be represented by n bits, and the range of values should be at least overwritten ( 2n1, 2n1). We use () brackets to denote an open interval, without endpoints, with [] parentheses to denote closed intervals, including endpoints. For example, the signed char type is represented by 8 bit, and the range of 2 ' s complement notation is [128, 127], or it can be said to cover (128, 128), so this type of precision is 8.
2. Unsigned integer types with a precision of n should be represented by n bits, and the range of values is [0, 2n1].
3. The accuracy is N of the value range of the floatingpoint number type should at least overwrite ( 2n1, 2n1) integer value. Now to convert a type with a precision of m (value x) to a type with a precision of n, all possible cases are shown in the following table.
Table 1. How to do type conversions
Types to convert 
Conditions for N < m 
Case of N = = m 
Conditions for N > m 
Signed integer to signed integer 
Discard M.S. Mn bits (can overflow) 
Same value

Same value

unsigned integer to signed integer 
if (X < 2n1) Same value else impl.def. (Can overflow) 
if (X < 2n1) Same value else impl.def. (Can overflow) 
Same value

Floatingpoint to signed integer 
if ( X < 2n1) Trunc (X) Else imple.def. (Can overflow) 
if ( X < 2n1) Trunc (X) Else imple.def. (Can overflow) 
if ( X < 2n1) Trunc (X) Else imple.def. (Can overflow) 
Signed integer to unsigned integer 
if (0 <= x) x% 2N else impl.def. 
if (0 <= x) same value else X + 2N 
if (0 <= x) same value else X + 2N 
unsigned integer to unsigned integer 
X% 2N 
Same value

Same value

Floatingpoint to unsigned integer 
if (0 <= X < 2N) trunc (x) Else imple.def. (Can overflow) 
if (0 <= X < 2N) trunc (x) Else imple.def. (Can overflow) 
if (0 <= X < 2N) trunc (x) Else imple.def. (Can overflow) 
Signed integer to floatingpoint 
Keep sign, keep M.S. N1 bits 
Same value

Same value

unsigned integer to floatingpoint 
+ sign, keep M.S. N1 bits 
+ sign, keep M.S. N1 bits 
Same value

floatingpoin t to floatingpoint 
Keep M.S. N1 bits (CAN Overflow) 
Same value 
Same value 
Some of the abbreviations in the above table are described below: Impl.def. The IMPLEMENTATIONDEFINED;M.S Bit means that mostsignificant bit;trunc (x) represents the integer portion of x, which is truncate toward Zero;x% y is the modulo, and X and y are positive integers when the modulo operation is used in the table above. Similarly, this table is not intended for you to use intentionally, but to analyze the cause of the error when you make a mistake. Here are a few examples to illustrate the use of this table. For example, the float type to the short type, the corresponding table in the floatingpoint to signed integer line, you can see, regardless of the accuracy of the two types, processing is the same, if the value of the float type (32768.0, 32768.0 ), the fractional portion is truncated, and if the value of the float type exceeds this range, the result of the conversion is undefined and may result in an overflow, for example, short s = 32768.4; This statement GCC will report a warning. For example, to convert the int type to the unsigned short type, the unsigned integer to Unsignedinteger row in the corresponding table, if the value of the int type is positive, divide it by 216 to take the modulo, in fact, take its lower 16 bits, If the value of the int type is negative, the conversion result is not explicitly defined. For example, to convert the int type to the short type, the first row in the corresponding table signed the integer to signed integer, Throw away the high 16 bits of the int type value (M.S here). Including the sign bit, the M.S mentioned in the table above. It should be a nonsymbolic bit, but only 16 bits lower, which can also overflow, for example, short s =32769; This statement GCC will report a warning, For short s =32768, no warning is reported. In the last example, the short type is converted to int, which still corresponds to the first row in the table, and should be same value after conversion. How does that keep the value constant? Is it OK to fill 16 0 on top of the high? If the value of the short type is1, the complement is the hexadecimal FFFF, the 1 to be converted to int is required to become ffffffff, so 16 1 instead of 16 0 is required at the high. In other words
In other words, to maintain the value unchanged, the upper 1 or 0 depends on the original sign bit, which is called symbol extension (sign Extension).
C language Type conversion