C99 Standard 6.3.1.8 Translation
Some operands that require an arithmetic type operator can lead to conversions and get the result type in a similar way. The purpose is to define a common real type for operands. For a given operand, each operand is converted to another type (without changing the Type field), and its corresponding true type is a generic real type. Unless otherwise explicitly stated, the true type of the generic is also the true type of the result, and if the operands are the same and complex, then the Type field of the result is the Type field of the operand. This pattern is called a regular arithmetic conversion.
1. If one of the operands is a long double, you do not need to change the Type field, and the other operand is converted to a long double;
2. Otherwise, if one of the operands is double, you do not need to change the Type field, and the other operand is converted to double;
3. Otherwise, if one of the operands is float, you do not need to change the Type field, and the other operand is converted to float;
4. Otherwise, the two operands will be integer-upgraded, and the rule should be applied in the promoted operand:
1) If the two operands are of the same type, no further conversions are required;
2) Otherwise, if the two operands are the same as signed or unsigned integers, the lower rank is converted to the higher rank person;
3) Otherwise, if the unsigned integer is greater than or equal to the signed integer, the signed integer is converted to an unsigned integer;
4) Otherwise, if a signed integer can represent all the ranges of an unsigned integer, the unsigned integer is converted to a signed integer;
5) Otherwise, the two operands are converted to unsigned operands, depending on the type of the signed operand.
C-language conventional arithmetic conversions