【C语言笔记】C语言数据类型转换
C语言中有很多数据类型,这些数据类型在内存中的存储形式不一样,为了计算方便,编译器不得不将某一种数据类型转换成另一种数据类型。本篇将介绍C语言中各种数据类型转换的规则。
一、自动类型转换(隐式转换)
自动类型转换指的是编译器在编译时自动的、隐式的进行的类型转换。
1、赋值时的类型转换
将一种类型的数据赋值给另一种类型的数据时,就会发生自动类型转换,例如:
double d = 5;
5是int类型的数据,而d是double类型的数据,在赋值时就会先把5转换成double类型的数据再赋值给d。
当然,把变量赋值给变量也会发生类型转换,例如:
float f = d;
编译器会把d先转换float类型的数据再赋值给f。
2、整形提升
整形提升是指再做整形运算时,把短整型(short)或字符整形(char)提升为缺省整形(int)再进行运算的一种机制。
下面这段引文说明了整形提升的意义:
表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度
一般就是int的字节长度,同时也是CPU的通用寄存器的长度。
因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长
度。
通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令
中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转
换为int或unsigned int,然后才能送入CPU去执行运算。
也就是说,整形数据只要参与运算就都会被提升为int类型。
整形提升的规则:
整形提升是按照变量的数据类型的符号位类提升的,提升的时候高位补的是符号位,例如:
char ch = 3;
int n = ch; // 要将ch赋值给n,就要进行整形提升
// 内存中的ch:
// 00000011
// ch是有符号char所以高位补的是符号位0
// 00000000 00000000 00000000 00000011
// 所以赋给n的就是:
// 00000000 00000000 00000000 00000011
再例如:
char ch = -3;
int n = ch; // 要将ch赋值给n,就要进行整形提升
// 内存中的ch(补码):
// 11111101
// ch是有符号char所以高位补的是符号位1
// 11111111 11111111 11111111 11111101
// 所以赋给n的就是:
// 11111111 11111111 11111111 11111101
对于无符号整型,高位统一补0:
unsigned char ch = 128;
int n = ch;
// 内存中的ch:
// 10000000
// ch是无符号的char,所以高位补0,不再是1
// 00000000 00000000 00000000 10000000
// 所以赋给n的就是:
// 00000000 00000000 00000000 10000000
3、算数转换
许多操作符的操作数不止一个,这些操作数在进行运算的时候如果不统一类型,运算将无法进行,那么在不同类型的数据进行运算时,必须将一个类型的数据转换成另一个类型的数据,这就是算数转换。
算数转换一般都是向着精度更高,长度更长的类型转换,所以就有了下面这些顺序:
long double
double
float
unsigned long int
long int
unsigned int
int
以上类型从上至下排名较低的在运算时就要先转换成另外一个操作数。
二、强制类型转换
强制类型转换就是由程序员控制的,将一种类型转换成另一种数据类型的类型转换。
1、强制类型转换的规则
强制类型转换的语法格式为:
(type_name)exp
type_name为新类型名称,exp为表达式。就比如:
double d = (double)5;
5是int类型数据,强将5转换成double类型数据再赋值给d。
这里有一个示例:
#include <stdio.h>
int main() {
int a = 3;
int b = 6;
int avg1 = 0;
double avg2 = 0;
avg1 = (a + b) / 2;
avg2 = (double)(a + b) / 2;
printf("%d, %.2lf", avg1, avg2); // 运行结果:4, 4.50
return 0;
}
在计算avg1时,(a + b) 和2都是int类型,那结果自然也是int类型,在计算avg2时候,(a + b) 先被转换成了double类型,而后为了运算正确,又要将ine类型的2进行算术转换成double类型,所以算出的结果是double类型,正确的赋值给了avg2。
2、类型转换只是临时的
我们需要注意的是,不论是自动类型转换还是强制类型转换,都只是为了本次运算正确而临时进行的,不会对原来的数据进行更改,转换后的数据也只是被临时储存了起来。
请看下面这个示例说明:
#include <stdio.h>
int main() {
int a = 10;
int b = 3;
double c = (double)a;
printf("%d, %d\n", sizeof(a), sizeof(c)); // 运行结果: 4, 8
//强制类型转换之后a的长度还是4,说明a本身并没有转换成double类型
double sum = (double)a / b;
printf("%.2lf\n", sum); // 运行结果:3.33
printf("%d\n", sizeof(b)); // 运行结果: 4
// 在计算时,为了正确b会被自动类型转换成double类型,但过后b的类型还是int,
// 这说明自动类型转换也是临时的
return 0;
}
一、类型转换的规则
不管是自动类型转换还是强制类型转换,都遵循着一些统一的规则。
1、有符号整形和无符号整形之间的转换
1)、如果有符号整形和无符号整型的位数相同,如果有符号整形不是负数,则它的数值不会发生改变.
2)、如果无符号整型的位数较大,则先将有符号整形提升为与无符号整型位数相同的有符号整形。然后再与无符号整数的最大数+1得到值相加,将有符号整形转换成无符号整型。
3)、如果无符号的位数较小,则除以“无符号数最大值+1”,将有符号整形转换成无符号整型。
2、浮点型和整形之间的转换
1)、将浮点型数据转换成整形数据时,会截断小数部分,只保留整数部分。
2)、将整形数据转换成浮点项数据时,如果转换后的结果在数值范围内不能被正确表示,则编译器会根据自己的方法取大于或小于的最接近的近似值作为转换结果。
3、浮点型和浮点型之间的转换
1)、float类型提升为double类型或long double或者double类型提升为long double是,数值不会发生变换。
2)、double类型转换成float类型或者long double转换成float类型时,会根据编译器自己定义的方法取大于或小于原值的近似值作为转换结果。