在C语言中,数据类型转换一般可分为隐式转换和显式转换,也称为自动转换和强制转换。其中,常见的隐式转换有4种,如下所示。
1)一般算术转换:通过某些运算符将操作数的值从一种类型自动转换成另一种类型,这一规则为“由低级向高级转换",具体如图所示。
根据图1所示的规则可知,若参与运算的变量类型不同,则先将变量的类型转换成同一类型,然后再进行运算。例如,int类型的变量和long类型的变量参与运算时,则会先把int类型的变量转成long类型,然后再进行运算。
这里需要特别注意的是,所有的浮点运算都是以双精度进行,即使表达式中仅含float单精度变量,也要先将其转换成double类型后再进行运算。同时,如果char类型的变量和short类型的变量参与运算,则必须先转换成int类型。
2)输出转换:输出的操作数类型与输出的格式不一致时所进行的数据类型的转换。
3)赋值转换:在赋值运算过程中将赋值运算符右侧的操作数类型转换成左侧操作数据的类型。
4)函数调用转换:当实参类型和形参类型不一致时数据所进行的转换。同样,显式转换也提供了两种转换方法,如下所示。
5)强制性数据类型转换:它是将一种类型的数据强制转换成为另一种数据类型。其格式为:
(数据类型标识符)表达式;
其作用是将表达式的数据类型强制转换成数据类型标识符所表示的类型。示例代码如下所示:
int i1=321 ;
float f4=(float)i1/9.0f;
6)利用C语言提供的标准函数转换,示例代码如下所示:
int i1;
char *c;
c="123";
i1=atoi(c);
printf("&d",i1);
关于浮点类型数据的转换原则,在C99的做了非常重要的阐述,
其表达的主要意思如下:
当我们将一个浮点类型的数据转换成除_ Bool 类型之外的一个整型数据时,该浮点数的小数部分须被丢弃,只保留它的整数部分。如果浮点数整数部分的值无法使用这种整型表示方法时,其行为是未定义的。
与此同时,如果我们将一个整数类型的数据转换成一个浮点类型时,如果该整型数据的值在该浮点数的取值范围内,并且能够被浮点类型精确表示,那么将会被正确转换;如果该整型数据的值在该浮点数的取值范围内,但不能够被浮点类型精确表示,那么转换的结果是最邻近的稍大或者稍小的可表示值;但如果该整型数据的值在该浮点数的取值范围外,其行为是未定义的。
当我们将一个double类型降级转换为float 类型、将long double类型降级转换到double或者float类型时,如果转换的值在新类型的取值范围内,并且能够被新类型精确表示,那么,将会被正确转换;如果转换的值在新类型的取值范围内,但不能够被新类型精确表示,那么转换的结果是最邻近的稍大或者稍小的可表示值;但如果转换的值在新类型的取值范围外,其行为是未定义的。
由此可见,为了避免浮点数据转换时导致的未定义行为,我们应该在转换时对数据进行相关的范围检查。例如,下面的代码演示了如何将double类型转换为int类型。
在上面的程序中,我们通过语句if(d1(double)INT_ MAXld1<(double)INT_ _MIN)
来对程序做类型转换时的取值范围检查,这样就可以避免在执行语句“il=(int)d1" 时发生未定义行为。
但需要特别强调的是,上面的程序是建立在double类型的取值范围大于int类型的取值范围的基础之上的。因此,在使用这种方法做取值范围检查时,你必须完全明白不同编译器所对应的相关类型的取值范围。假设在某个编译器中,double 类型的取值范围小于int类型的取值范围,那么上面这种方法将是不可行的,实际上这种情况基本没有。相对于浮点数与整数之间的转换,浮点数与浮点数之间的转换就简单多了。