数据类型转换
自动类型转换
当一个表达式含有几个不同类型的操作数时,就需要应用一些规则将操作数转换为同一类型进行求值。
int a = 3;
double b = 4;
a + b; // int + double
- 在表达式 a+b 的求值过程中,会先将a转换为double类型再与b求和。
- 在 b=4; 赋值语句中,也存在int到double的转换。
这种将窄类型转型为宽类型且不会丢失信息的变换,通常程序可以自动完成,称为自动类型转换或隐式类型转换,这里宽窄是指用sizeof计算的数据类型字节数。类型转换也暗示了类型拥有等级的概念,浮点类型高于整型类型。下图展示了各类型之间的等级转换关系:同等类型从左向右转,不同层次由低向高转。
(低) (高)
------------------------ ↑
float ---> double | 浮点类型 (高)
|
char ---> int | 整型类型 (低)
------------------------->
目前我们对浮点数的表示使用的是double类型,称为双精度浮点类型。此外C语言还提供了float这种单精度浮点类型,它所能存储的数值精度比double小。
float pi = 3.14f;
printf("pi: %f\n", pi)
默认的浮点字面量是double类型,在后面追加'f'标记,将指示字面量为float类型。通常sizeof(float)与 sizeof(int)都是4个字节。但是由于float是比int更高等级的类型, 故而在 int op float 中,int会自动转型为float,表达式结果将是float类型。最后,表达式中的类型转换是逐项进行的,而不是一次转型到结果目标类型。在下面的示例中,我们以t表示单步表达式计算的中间结果,箭头后面是该项表达式的结果类型,!号表示这里发生了自动类型转换。
int a = 3;
int b = 4;
float s = 1.5f;
double r = 0.7;
a / b * s + r; // #1: t = a / b int / int --> int
// #2: t = t * s !float * float --> float
// #3: t = t + r !double + double --> double
强制类型转换
有时我们也需要将较宽的数据类型转换为较窄的数据类型,或在两种不同的数据类型之间进行转换。这时可以使用显示类型转换,也称为强制类型转换,语法表示为:(目标类型)表达式
#include <stdio.h>
int main()
{
float a = 45.7f;
float b = 70.5f;
int c = (int)a + (int)b;
int d = (int)(a + b);
printf("c = %d\n", c);
printf("d = %d\n", d);
return 0;
}

- 计算c的过程中,a与b分别被强制转换为int型,转型并不会发生舍入操作,相当于求45+70的值。
- 计算d的过程中,先计算两个float的和,然后将结果转换为int型。
数值溢出
当从较宽的数据类型转换到较窄的数据类型时,在现代编译器上,这可以自动完成。由于较宽数据类型存储的数值可能会超过较窄数据类型的表达范围,这可能并不是我们想要的结果。下图展示了从int转换到char的过程 ,左侧的图例中,被丢弃的字节全是0,c与a的值都是65,看起来并没有什么影响;右侧a的初始值是6000,转型后只保留最低位一个字节,c的值为112。
+-------------------+ +-------------------+
| 00 | 00 | 00 | 41 | int a = 65; | 00 | 00 | 17 | 70 | int a = 6000;
+-------------------+ +-------------------+
--- discard -- | 41 | char c = a; --- discard -- | 70 | char c = a;
+----+ +----+
这些情况下建议使用显示类型转换,突出强调作用:我强制将大类型转换为小类型,有潜在数据丢失风险!
#include <stdio.h>
int main()
{
int a = 65;
/*
这里int自动转换到了char
由于c的大小足以存储结果值,因此值意义是上正确的
*/
char c = a;
printf( "%d, %c\n", c, c );
/* a的值已经超过c的可存储范围,因此发生想不到的结果 */
a = 6000;
c = a;
printf( "%d, %c\n", c, c );
return 0;
}
数值a的二进值表达为 0001 0111 0111 0000,字符 c 仅能够容纳其低8位值。在将a赋值给c后,c的值就是 0111 0000,即十进制的112。

陕公网安备61011202001108号