10.6 数据类型转换
第4章“数据类型和表达式”曾简要地说明,在表达式求值的过程中,系统有时会进行隐式的数据类型转换。你验证的例子是float和int数据类型。你看到了涉及一个float和一个int的运算如何作为浮点运算进行求值,整型数被自动转换成为浮点型。
你还看到了如何使用类型转换运算符显式地控制转换。因此,假设total和n都是整型变量,
average=(float)total/n;
在运算之前,变量total的值被转换为float型,这就保证了将除法运算作为浮点运算求值。
10.6.1 转换规则
对含有不同类型数据的表达式求值时,Objective-C编译器会遵循一些非常严格的规则。
下面总结了表达式求值过程中,不同类型操作数发生转换的先后顺序:
1.如果其中一个操作数是long double型,则另一操作数被转换为long double型,计算结果也是这种类型。
2.如果其中一个操作数是double型,则另一操作数转换为double型,计算结果也是这种类型。
3.如果其中一个操作数是float型,则另一操作数转换为float型,计算结果也是这种类型。
4.如果其中一个操作数是_Bool、char、short int、bit field[1]或枚举数据类型,则全部转换为int型。
5.如果其中一个操作数是long long int型,则另一操作数转换为long long int型,计算结果也是这种类型。
6.如果其中一个操作数是long int型,则另一操作数转换为long int型,计算结果也是这种类型。
7.如果到达这一步,则可知两个操作数均为int型,计算结果也是这种类型。
以上列出的实际上只是表达式中操作数类型转换过程涉及步骤的简化版本。涉及unsigned操作数时,规则还会更复杂。在附录B“Objective-C语言总结”中,可以看到完整的转换规则。
从这一系列步骤中可以认识到,只要到达“计算结果也是这种类型”,转换过程就结束了。
举一个例子说明如何遵循这些步骤。观察以下表达式的求值方式。其中f定义为float变量,i为int变量,l为long int变量,s为short int变量:
f*i+l/s
首先考虑f和i的相乘运算,这是float和int相乘。由步骤3可知,由于f是float型,另外一个操作数(i)会被转换为float类型,相乘的结果也是float。
下一步,考虑l和s的除法运算,这是long int除以short int。由步骤4可知short int会被转换为int,然后,步骤6表明,由于其中一个操作数(l)是long int类型,所以另一个操作数将被转换为long int,计算结果也是这个类型。因此,这个除法的结果是long int类型,实际上删节了除法运算结果的小数部分。
最后,按照步骤3,如果表达式中一个操作数为float类型(变量f和i相乘的结果),则另一个操作数将被转换为float类型,运算结果也是float类型。因此,在l和s的除法运算完成之后,其结果将被转换为float类型,然后和f和i的乘积相加。整个表达式的最终计算结果是float类型的值。
记住,总能使用类型转换运算符显式地强制类型转换,从而控制特定表达式的求值方式。
因此,在前面的表达式求值过程中,如果不希望l和s相除得到截取的结果,可以将其中一个变量转换为float类型,这样就能强制表达式作为浮点除法求值,如下所示:
f*i+(float)l/s
在这个表达式中,由于类型转换运算符比除法运算符的优先级高,所以l首先转换为float,然后进行除法运算。因为这个除法运算中一个操作数变成了float类型,所以,其他一个或多个操作数也会自动转成float类型,计算结果也是这个类型。
[1]第13章节简要地讨论了bit field。