类型转换

隐式转换

即不需要程序员手动添加转换规则,而是由编译器自动转换,为了避免隐式转换可能带来的安全隐患(不被程序员控制,可能导致数据溢出),需要列举出会发生隐式转换的情况。总的来说,当给定的类型与需要的类型不同时,就可能发生隐式转换。

  1. 如果操作数中有任何低于 int 和 unsigned int 的类型,会首先将该操作数转换为 int 类型或者 unsigned int 类型,这个过程我们称之为整数提升
  2. int –> long –> long long –> float –> double –> long double(等级由低到高,低等级向高等级隐式转换)
  3. 同一转换等级的有符号整数和无符号整数一起参与运算时:有符号整数会转换成对应的无符号整数

最好尽量避免使用无符号整数,特别是不要把它和有符号整数混合使用。(无符号整数一般用于底层开发中,在应用层面很少会使用)。

1
2
3
4
int i = -10;
unsigned int u = 10;
if(i < u)
printf("i is less than u\n");

由于 int 会向 unsigned int 转换(因为你在 if 判断语句中 用 int 类型数据和 unsigned int 数据进行比较),导致 i 会变成一个非常大的数,所以出现不符合题意的判断了。

显式转换

需要程序员手动给出需要强转的类型。比方说将 int 类型强制转换为 float 类型。

1
2
3
int x = 10;

printf(" x = %f\n", (float)x);

那为什么需要显示转换呢?

  1. 使用强制类型转换显示表明肯定会发生的转换
  2. 使用强制类型转换进行我们需要的类型转换
  3. 可以用强制类型转换计算浮点数的小数部分
  4. 可以使用强制类型转换来避免溢出

示例:可以用强制类型转换计算浮点数的小数部分

1
2
3
4
5
6
void fun() {
float num2 = 3.176;
float num1 = num2 - (int)num2;

printf("%f", num1); // 0.176000
}

示例:可以使用强制类型转换来避免溢出

1
2
3
4
5
void fun() {
long long millisPerDay = 24 * 60 * 60 * 1000;
long long nanosPerDay = 24 * 60 * 60 * 1000 * 1000 * 1000;
printf("%lld\n", nanosPerDay / millisPerDay); // 1000000
}

millisPerDay 和 nanosPerDay 变量没有溢出,但不代表 等号 右边的数据没有溢出。即哪怕是常量也是有数据类型的,那就意味着有一定的存储范围, 24 * 60 * 60 * 1000 * 1000 * 1000 这是 6 个 int 类型的数据相乘,完全超出 int 数据类型表示的范围了。

1
2
3
4
5
void fun() {
long long millisPerDay = 24 * 60 * 60 * 1000;
long long nanosPerDay = (double)24 * 60 * 60 * 1000 * 1000 * 1000;
printf("%lld\n", nanosPerDay / millisPerDay);
}

注意:强制转换中,如果宽度长的转换到宽度低的会丢失精度。