C语言数据类型转换(自动类型转换+强制类型转换)
自动类型转换
自动类型转换就是编译器默默地、隐式地、偷偷地进行的数据类型转换,这种转换不需要程序员干预,会自动发生。
1)将一种类型的数据赋值给另外一种类型的变量时就会发生自动类型转换,例如
float f = 100;
100是int 类型的数据,需要先转换为float类型才能赋值给变量f。再如
int n = f;
f是float类型的数据,需要先转换为int类型才能赋值给变量n。
在赋值运算中,赋值号两边的数据类型不同时,需要把右边表达式的类型转换为左边变量的类型,这可能会导致数据失真,或者精度降低;所以说,自动类型转换并不一定是安全的。对于不安全的类型转换,编译器一般会给出警告。
2)在不同类型的混合运算中,编译器也会自动地转换数据类型,将参与运算的所有数据先转换为同一种类型,然后再进行计算。转换的规则如下:
转换按数据长度增加的方向进行,以保证数值不失真,或者精度不降低。例如,int 和 long 参与运算时,先把 int 类型的数据转成 long 类型后再进行运算。
所有的浮点运算都是以双精度进行的,即使运算中只有 float 类型,也要先转换为 double 类型,才能进行运算。
char 和 short 参与运算时,必须先转换成 int 类型。
自动类型转换示例:
//自动类型转换实例
#include <stdio.h>
int main(){
float PI = 3.14159;
int r = 5;
int s1;
double s2;
s1 = r*r*PI; //s1=78
//在计算表达式r*r*PI时,r和PI都被转换成 double 类型,
//表达式的结果也是 double 类型。
//但由于 s1 为整型,所以赋值运算的结果仍为整型,
//舍去了小数部分,导致数据失真。
s2 = r*r*PI; //s2=78.539749
printf("s1=%d s2=%f\n", s1, s2);
return 0;
}
强制类型转换
自动类型转换是编译器根据代码的上下文环境自行判断的结果,有时候并不是那么“智能”,不能满足所有的需求。如果需要,程序员也可以自己在代码中明确地提出要进行类型转换,这称为强制类型转换。
自动类型转换不需要程序员干预,强制类型转换必须有程序员干预。
强制类型转换的格式为:
(type_name) expression
type_name为新类型名称,expression为表达式。例如:
(float) a; //将变量 a 转换为 float 类型
(int)(x+y); //把表达式 x+y 的结果转换为 int 整型
(float) 100; //将数值 100(默认为int类型)转换为 float 类型
下面是一个需要强制类型转换的经典例子:
//强制类型转换
int main()
{
int sum = 103; //总数
int count = 7; //数目
double average; //平均数
average = (double)sum/count;
printf("Average is %lf!\n", average);
return 0;
}
sum和count都是int类型,如果不进行干预,那么sum/count的运算结果也是int类型,小数部分将被丢弃;即使average是double类型可以接收小数部分,但是心有余而力不足,因为运算完sum/count时已经是int类型了
其实只要将sum或者count其中之一转换为double类型即可,上面的代码中,我们将 sum 强制转换为 double 类型,这样sum / count的结果也将变成 double 类型,就可以保留小数部分了,average 接收到的值也会更加精确。
在这段代码中,有两点需要注意:
- 对于除法运算,如果除数和被除数都是整数,那么运算结果也是整数,如果不能整除,小数部分将被直接丢弃,只保留整数部分,这跟将小数赋值给整数类型是一个道理;如果除数和被除数其中有一个是小数,那么运算结果也是小数。
- ( )的优先级高于/,对于表达式(double) sum / count,会先执行(double) sum,将 sum 转换为 double 类型,然后再进行除法运算,这样运算结果也是 double 类型,能够保留小数部分。注意不要写作(double) (sum / count),这样写运算结果将是 3.000000,仍然不能保留小数部分。
类型转换只是临时性的
无论是自动类型转换还是强制类型转换,都只是为了本次运算而进行的临时性转换,转换的结果也会保存到临时的内存空间,不会改变数据本来的类型或者值。请看下面的例子:
#include <stdio.h>
int main()
{
double total = 400.8; //总价
int count = 5; //数目
double unit; //单价
int total_int = (int)total;
//total 变量被转换成了 int 类型才赋值给 total_int 变量
//而这种转换并未影响 total 变量本身的类型和值。
//如果 total 的值变了,那么 total 的输出结果将变为 400.000000;
unit = total / count;
//如果 total 的类型变了,那么 unit 的输出结果将变为 80.000000。
printf("total=%lf, total_int=%d, unit=%lf\n", total, total_int, unit);
return 0;
}
自动类型转换 VS 强制类型转换
在C语言中,有些类型既可以自动转换,也可以强制转换,例如 int 到 double,float 到 int 等;而有些类型只能强制转换,不能自动转换,例如以后将要学到的 void * 到 int *,int 到 char * 等。
可以自动转换的类型一定能够强制转换,但是,需要强制转换的类型不一定能够自动转换。
可以自动进行的类型转换一般风险较低,不会对程序带来严重的后果,例如,int 到 double 没有什么缺点,float 到 int 顶多是数值失真。只能强制进行的类型转换一般风险较高,或者行为匪夷所思,例如,char * 到 int * 就是很奇怪的一种转换,这会导致取得的值也很奇怪,再如,int 到 char * 就是风险极高的一种转换,一般会导致程序崩溃。