常用的算术类型转换为隐式转换,常用算术类型转换目标是为所有的操作数即操作结果寻找一个通用的类型。
常用的算术类型转换涉及以下操作数:
l 具有两个操作数的算术操作符: *, /, %, +和-
l 关系操作符: <, <=, >, >=, ==和!=
l 位操作符:&, |和^
l 条件操作符:?:
除关系操作符外,常用算术转换获得的公共实数类型通常为结果值的类型,然而,如果一个或多个操作数为复数类型,刚结果也具有复数类型。
常用算术转换的应用如下:
1. 如果任一个操作数为复数,此时,具有低转换等级的操作数转换为具有与其他操作数相同的类型,实数和虚数部分各自进行转换;
换句话说,如果一个操作数具有复数类型,通常算术转换仅匹配实数部分,下面是一些例子:
#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.
2. 如果两个操作数为整数,则先对两个操作数进行整型提升,在此之后,如果类型还不相同,这时,会以以下规则进行转换:
a) 如果一个操作数具有unsigned 类型T,且它的转换级别等于或高于其他操作数的类型,那么其它操作数将转换为类型T;
b) 否则,如果一个操作数具有signed类型T, 且其转换级别高于其它操作数类型,如果类型T足够大能够之前的所有类型值;如果不是,则两个操作数转换为类型T对应的无符号类型。
下面是一些例子:
Int I = -1;
Unsigned int limit = 200U;
Long n = 30L;
If ( I < limit)
X = limit * n;
在此例中,if条件中为比较语句, i的值为-1, 首先会转换为unsigned int,结果是一个很大的正数,在32位系统上,其值为232 – 1, 且在任何系统上,其值都大于limit,所以if条件为false.
例子中的最后一行,如果long的取值范围能够包含unsigned int的所有取值,则limit的值转换为变量n的类型long,如果不是,例如,int和long均为32位的宽度,则它们的类型将转换为unsigned long。
除了以一情景外,常用算术转换会保护操作数的值:
l 当一个巨大的整数转换为浮点类型时,目标类型的精度可能不足以精确地表示此数;
l 超出无符号类型取值范围的负数;
在这两种情景中,数值超过了目标类型的范围或精度,这种转换将在接下来的一节”算术类型转换的结果”中讲述。
在下列场景下,编译器也会自动转换算术值:
l 在分配或初始化,右操作数的值通常会转换为左操作数的类型;
l 在函数调用中,实参将转换为相应的形参类型,如果参数没有被声明,则会进行默认的参数提升,整型参数进行整型提升,float参数提升为double;
l 在return语句中,return表达式的值将转换为函数返回值的类型。
在一个复数的赋值语句中,例如x += 2.5, 两个操作数的值首先进行算术转换,所以运算的结果类型就为左操作数的类型,下面是一些例子:
#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.
}