不同类型数据之间的类型转换
不同类型数据之间的类型转换
机械语言的算术运算指令比C语言算术表达式的限制更多。为了让运算机执行机械指令中的算术运算,通常不仅要求两个操作数有相同的长度(字节数),而且还要求数据的存储方式也相同。比犹如是单精度浮点型数。
在C语言中,最好把同类型的常量值赋给同一类型的变量,或利用同类型的常量和变量进行算术运算或关系运算。
但是在C语言程序中,许诺在表达式中混合利用各类不同类型的数据。在一个表达式中,能够同时显现整型、浮点型、字符型的常量和变量。在这种情形下,C语言编译程序通常需要生成一些附加的指令,在执行一条运算类指令之前,将其中一个操作数的类型转换成另一个操作数的类型。
下面讨论的类型转换都是有符号型的变量和常量之间的类型转换,不涉及无符号的变量(和常量)。这适用于常规的应用范围。一些高级语言(比如Java语言),就只有有符号型的常量和变量。
类型转换分为自动类型转换和强制类型转换两种。自动类型转换指的是编译器在将语句(或表达时)翻译成指令时,由编译程序自动进行的类型转换。在以下四种情形中会显现自动类型转换:
1)二元算术运算符或关系运算符两边的操作数类型不一致。
2)赋值运算符两边的操作数类型不一致。
3)函数调历时实际参数与形式参数要求的类型不一致。
4)函数挪用终止时返回值的类型与要求的类型不一致。
其中,第3种和第4种类型转换讨论,请参见第7章。
本章以下仅讨论前两种情形下的自动类型转换。
(1)算术或关系表达式中的类型转换
在算术(或关系)表达式中,出此刻二元运算符双侧的运算量能够是不同类型的,这时就涉
及类型之间的转换问题。若是没有显现强制类型转换,那么简单的自动类型转换规那么分为三种:
1)只要两个操作数中显现了char类型或 short 型,第一都将无条件地自动提升为int型。
2)在两个操作数的类型都不是浮点型的情形下,自动进行了第一种规定的无条件的类型提升以后,依照以下方式对操作数的类型再次进行有条件的提升。那个条件是两个操作数当中有一个数是long型,即将int提升为long型。
举例来讲,关于“short  n1 ;  long  num;”,要求计算表达式n1 + num。编译器先将变量 n1自动提升为int型。由于两个操作数中有一个变量num是long型,因此,方才提升为int 型的变量n1的值将再次提升为long型。
延伸与拓展:整型类型提升的技术黑幕
增加临时寄存此数的字节和对这些字节进行符号位的扩展,这是由于运算机是用补码来表示有符号整数的。只有对补码进行符号位的扩展,补码表示的值才可不能改变。参见本章提高部份有关补码的讨论。
3)两个操作数都是浮点数或其中有一个是浮点数的情形下,提升规那么如下:long  double  (这是C99标准规定的类型)    ↑ double          ↑  float       
也确实是说:
若是在一个表达式(或一个二元算数或关系运算符)中显现了long  double 型的运算量,那么此表达式计算出的最终值是long double型的。
若是一个表达式(或一个二元算数或关系运算符)中显现了double 型的运算量(但没有显现long  double型量),那么此表达式计算出的最终值是double型的。
若是一个表达式(或一个二元算数或关系运算符)中显现了float 型的运算量(但没有显现double型量或long  double型量),那么此表达式计算出的最终值是float型的。
若是两个操作数中还有一个int型或 long 型的整型量,那么此整型数就会依照另一个浮点操作数的类型进行转换。
读者还要注意的是:数据类型的转换,并非是在计算表达式的值之前一次性完成的,而是依照规定的运算顺序,慢慢进行类型转换的。例如,关于如下表达式:
56.91+'A'*32
是先依照转换规那么,将char型的量'A'转变成int型值(第一种类型提升)进行乘法运算;取得一个整数值以后,再依照转换规那么转变成double型(这是由于前一个参与运算的常量59.61被系统默以为double型常量),然后再与56.91进行双精度浮点数加法运算。(2)赋值语句(或赋值表达式)中的类型转换
在赋值语句(或赋值表达式)中,若是赋值运算符右边表达式计算结果的类型与左侧变量的类型不一致,那么会自动进行类型转换。类型转换的规那么很简单:将表达式计算出的值转变成赋值号左侧变量的类型。
若是赋值号右边的数据类型的取值范围宽于左侧变量类型的取值范围,通常会发生精度的额外丢失或错误。
例如,若是概念“char  d_char ;  int  d_int ;  float  d_float ;  double  d_double ;”,那么以下赋值语句(或赋值表达式)是可不能有任何问题的,因为右边的数据类型“不宽于”左侧变量类型的取值范围。d_int = d_char;d_float = d_int;d_double = d_float;
可是,若是将以上几条赋值语句(或赋值表达式)中的变量调换位置:d_char= d_int;d_int =d_float;d_float= d_double;
攻击类型转换通常都会显现问题。
关于第1条语句“d_char= d_int;”,在d_int的值超过255时,在char只占8位内存的运算机上必然犯错(溢出)。即便d_int的取值在128~255之间,也不必然正确。这要看你正在利用的C编译器中,char类型本质上究竟是有符号的整数(取值在–128~127之间)仍是无符号的整数(取值在0~255之间)。若是是前者,就会显现把一个正整数变成了一个负整数而且寄存到变量d_char中的错误。
关于第2条语句“d_int =d_float;”,必然会使d_float的小数部份丢失(可不能四舍五入)。更为严峻的是,若是d_float的值超出了int类型的取值范围(这或许是很常见的,因为有些C编译器中,int型的最大值是32767),那么变量d_int中的值也必然犯错(溢出)。
第3条语句的情形,读者可自行分析。
(3)强制类型转换
若是自动类型转换知足不了需要,那么能够要求编译程序进行强制类型转换。强制类型转换是通过利用强制类型转换运算符(由圆括号括住类型名组成)来实现的。其格式为:(类型名)(被转换的表达式)

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。