C语言自动类型转换和强制类型转换详解
计算机硬件进行算术操作时,要求各操作数的类型具有相同的大小(存储位数)及存储方式。例如,由于各操作数大小不同,硬件不能将 char 型( 1 字节)数据与 int 型( 2 或 4 字节)数据直接参与运算;由于存储方式的不同,也不能将 int 型数据与 float 型数据直接参与运算。
然而,由于 C 语言编程的灵活性,在一个表达式或一条语句中,允许不同类型的数据混合运算。
C 语言的灵活性与计算机硬件的机械性是一对矛盾,如处理不好,将会产生错误结果。对于某些类型的转换编译器可隐式地自动进行,不需人工干预,称这种转换为自动类型转换;而有些类型转换需要编程者显式指定,通常,把这种类型转换称为强制类型转换。
不同数据类型之间的差别在于数据的表示范围及精度上,一般情况下,数据的表示范围越大、精度越高,其类型也越“高级”。
整型类型级别从低到高依次为:
1) 操作数中没有浮点型数据时:
当 char、unsigned char、short 或 unsigned short 出现在表达式中参与运算时,一般将其自动转换为 int 类型,特殊情况下 unsigned short 也可能转换成 unsigned int(如 Turbo C2.0 中,short 和 int 所占字节数相同,unsigned short 的正数表示范围比 int 大,故将其转换为 unsigned int)。
int 与 unsigned int混合运算时:
2) 橾作数中有浮点型数据时:
当操作数中含有浮点型数据(float 或 double)时,所有操作数都将转换为 double 型。
例如:
3) 赋值运算符两恻的类型不一致时:
当赋值运算符的右值(可能为常量、变量或表达式)类型与左值类型不一致时,将右值类型可能提升或降低为左值类型。例如:
4) 右值超出左值类型范围时:
更糟糕的情况是,赋值运算符右值的范围超出了左值类型的表示范围,将把该右值截断后,赋给左值。所得结果可能毫无意义。例如:
当 return 后的表达式类型与函数的返回值类型不一致时,也会自动把 return 后表达式的值转换为函数类型后,再返回。
当函数调用时,所传实参与形参类型不一致时,也会把实参自动转换为形参类型后再赋值。
为了给程序设计人员提供更多的类型转换控制权限,使程序设计更加灵活,转换的目的更加清晰,C 语言提供了可显式指定类型转换的语法支持,通常称之为强制类型转换。
强制类型转换的格式为:
而如果采用如下的自动类型转换:
然而,由于 C 语言编程的灵活性,在一个表达式或一条语句中,允许不同类型的数据混合运算。
C 语言的灵活性与计算机硬件的机械性是一对矛盾,如处理不好,将会产生错误结果。对于某些类型的转换编译器可隐式地自动进行,不需人工干预,称这种转换为自动类型转换;而有些类型转换需要编程者显式指定,通常,把这种类型转换称为强制类型转换。
自动类型转换
一个表达式中出现不同类型间的混合运算,较低类型将自动向较高类型转换。不同数据类型之间的差别在于数据的表示范围及精度上,一般情况下,数据的表示范围越大、精度越高,其类型也越“高级”。
整型类型级别从低到高依次为:
int -> unsigned int -> long -> unsigned long -> long long -> unsigned long long
浮点型级别从低到高依次为:float -> double
1) 操作数中没有浮点型数据时:
当 char、unsigned char、short 或 unsigned short 出现在表达式中参与运算时,一般将其自动转换为 int 类型,特殊情况下 unsigned short 也可能转换成 unsigned int(如 Turbo C2.0 中,short 和 int 所占字节数相同,unsigned short 的正数表示范围比 int 大,故将其转换为 unsigned int)。
int 与 unsigned int混合运算时:
int -> unsigned int
int、unsigned int 与 long 混合运算时,均转换为 long 类型。2) 橾作数中有浮点型数据时:
当操作数中含有浮点型数据(float 或 double)时,所有操作数都将转换为 double 型。
例如:
3+5.3f+1.7上述算术表达式中操作数 1.7 为双精度浮点数,故先把 3 和单精度浮点数 5.3 自动提升为双精度浮点数后,参与运算。运算结果为双精度浮点数 10.0。
3) 赋值运算符两恻的类型不一致时:
当赋值运算符的右值(可能为常量、变量或表达式)类型与左值类型不一致时,将右值类型可能提升或降低为左值类型。例如:
double d; d=5.1f;由于左值为双精度浮点型,故先把右值单精度浮点型常量 5.1 提升为双精度浮点型后,再赋值给 d,不但不丢失精度反而提高了精度。
int i; i=5.1; //右值5.1为双精度,左值为整型右值双精度浮点型 5.1 降低为左值整型,即 5.1 舍弃小数部分后,把 5 赋给整型变量 i,这种情况会丢失精度。
4) 右值超出左值类型范围时:
更糟糕的情况是,赋值运算符右值的范围超出了左值类型的表示范围,将把该右值截断后,赋给左值。所得结果可能毫无意义。例如:
char c; //char 占8位,表示范围-127〜128 c=1025; //1025 对应二进制形式:100 0000 0001,超出了8位 printf("%d",c) ; //以十进制输出c的值该输出结果为 1,因为只取 1025 低 8 位 0000 0001(值为1),赋给字符型变量 c,故得到毫无意义的值。
当 return 后的表达式类型与函数的返回值类型不一致时,也会自动把 return 后表达式的值转换为函数类型后,再返回。
当函数调用时,所传实参与形参类型不一致时,也会把实参自动转换为形参类型后再赋值。
强制类型转换
虽然自动类型转换不需要人工干预,使用方便,但有利也有弊,尤其当自动类型转换是从较高类型转换为较低类型时,将会降低精度或截断数据,可能得不到预期的结果。为了给程序设计人员提供更多的类型转换控制权限,使程序设计更加灵活,转换的目的更加清晰,C 语言提供了可显式指定类型转换的语法支持,通常称之为强制类型转换。
强制类型转换的格式为:
(目标类型) 表达式
例如,计算某工厂目前可出厂的产品总件数用 total 表示,该工厂共有三个车间,已知:1 车间目前完成 10.9 件,2 车间目前完成 12.7 件,3 车间目前完成 11.8 件。则:int total; total=(int)10.9+(int)12.7+(int)11.8;故 total=10+12+11=33,符合题意。
而如果采用如下的自动类型转换:
int total=10.9+12.7+11.8;其值将为 35。因为赋值运算符右端表达式 10.9+12.7+11.8=35.4 为双精度浮点型,而左值 total 类型为整型,将 35.4 自动转换为整数 35 后赋给 total。与题意不符。