首页 > 编程笔记 > C语言笔记 阅读:348

C语言类型转换详解(自动类型转换和强制类型转换)

C语言的数据类型有很多种,如字符型、整型、长整型和浮点型等,这些类型的变量、长度和符号特性都不同,取值范围也不同。

C语言的类型之间可以互相转换,转换的过程就像倒水。如下图所示,小杯的水倒进大杯,水不会流失。但是,如果大杯的水倒进小杯,水就会溢出来。


图 1 类型转换的过程就像倒水

数据也是相似的,取值范围较大的数据就像大杯里的水,取值范围较小的数据就像小杯里的水。如果把取值范围较大的数值类型变量的值赋给取值范围比较小的数值类型变量,那么数据就会缩小取值范围表示,当数据大小超过数值类型的可表示范围时,就会发生数据截断,就如同水溢出。

C语言自动类型转换

对于 C语言来说,如果把取值范围比较小的数值类型变量的值赋给取值范围比较大的数值类型变量,那么取值范围比较小的数值类型变量中的值会升级表示为取值范围比较大的数值类型,数据信息不会丢失。这类转换被称为自动类型转换。

例如:
float i=10.1f;
int j=i;
默认类型会造成一些“雷区”。C语言代码中整数的默认类型是 int,浮点数的默认类型是 double。如果一个公式里的数字都是整数,那么这个公式的计算结果默认是 int 类型。

例如,给 long 类型赋值一个公式的计算结果,如果这么写:
long a = 123456789 * 987654321;
计算后会发现 a 的值居然是 -67153019,这是因为等号后面没有指定数字的类型,所以默认按照 int 值做了计算,计算结果又超出了 int 类型的最大范围,就变成了溢出的结果。

这行代码实际的运算过程是这样的:
int i = 123456789 * 987654321;
long a = (long) i;

解决这个问题的办法是在公式计算之前提升数字的精度。给数字添加 L 后缀,数字就变成了 long 类型,编译器会采用公式中精度最高的类型记录计算结果。上面的代码有 3 种修改方式,修改如下:
long a = 123456789L * 987654321; // 给第一个数添加L后缀
long a = 123456789 * 987654321L; // 给第二个数添加L后缀
long a = 123456789L * 987654321L; // 给两个数都添加L后缀
这样计算后 a 的值就是正确的 121932631112635269。

同样的情况也会发生在浮点数的应用中,例如,计算 5 除以 2,如果这么写:
double b = 5 / 2;
计算后会发现 b 的值居然是 2.0,而不是正确的 2.5。造成这个问题的原因与刚才的 long 类型问题的一样,这行代码的实际运算过程是这样的:
int i = 5 / 2;
double b = (double) i;
解决这个问题的办法同样是提升数字的精度,修改方式如下:
double b = 5.0 / 2; // 把第一个数改为浮点数
double b = 5 / 2.0; // 把第二个数改为浮点数
double b = 5.0 / 2.0; // 把两个数都改为浮点数
这样计算后 b 的值就是正确的 2.5。

C语言强制类型转换

强制类型转换是取值范围比较大的数值类型变量的值赋给取值范围比较小的数值类型变量,转换的过程就像大杯向小杯里倒水,可能会有水溢出,也就是数据会丢失。

如果程序需要进行强制类型转换,就会出现下图所示的程序警告。当进行类型的强制转换之后,警告就会消失。


强制类型转换的一般形式如下:
(类型名) (表达式)
例如,对不同变量进行类型转换时使用强制类型转换的方法:
int secret1=103;
char answer1= (char) secret1; /*进行强制类型转换*/
从代码中可以看到:在变量前使用包含要转换类型的括号,这样就对变量进行了强制类型转换。

如果某个表达式要进行强制类型转换,需要将表达式用括号标识,否则会只对第一个变量或常量进行强制类型转换。例如:
double x=4.1415926,y=5.79865; /*定义2个浮点型变量并赋值*/
int z=(int)(x+y); /*将表达式x+y的结果强制转换为整型*/

相关文章