C语言强制类型转换

目录

1.浮点型的存储方式

1.1.浮点型存储方式

1.2.数值计算表达式

1.3.存储详解

2.类型强制转换

2.1.指针类型强转

2.2.变量类型强转


 

 

 

1.浮点型的存储方式

1.1.浮点型存储方式

(1)float类型在内存中的存储方式:

(2)double类型在内存中的存储方式:

 

1.2.数值计算表达式

gif.latex?X%3D%28-1%29%5E%7BS%7D*M*2%5E%7BE%7D

~ S  为符号位   0表示整数,1表示负

~E   在 32 位浮点型中,指数位阶码是 8 个比特位,则可以表示的指数范围为0~255,但是指数有正数也有负数,为了表示 -126 ~127,则对每次存储的指数值加上偏移值gif.latex?2%5E%7B8-1%7D%20%3D%20127,读取时在自动减去127。这样指数位为127时表示实际指数为0,指数位大于127表示正指数,指数位小于127表示负指数。指数位阶码位全为 1 和全为 0 用作特殊情况,剩下阶码取值从 1 到 254,减去偏移值后得到指数取值从 -126 到 127。

~E   在 64 位浮点型中,指数位阶码是 11个比特位,则可以表示的指数范围为0~2047,但是指数有正数也有负数,为了表示 -1022 ~1023,则对每次存储的指数值加上偏移值gif.latex?2%5E%7B11-1%7D-1%20%3D%201023,读取时在自动减去1023。这样指数位为1023时表示实际指数为0,指数位大于127表示正指数,指数位小于1023表示负指数。指数位阶码位全为 1 和全为 0 用作特殊情况,剩下阶码取值从 1 到 2046,减去偏移值后得到指数取值从 -1022到 1023。

 

 

~M  表示科学记数法中的尾数部分,由于正规化的浮点数小数点前总是[ 1 , 2 ),所以尾数位实际上省略了小数点前的1。例如尾数位值为 1001,则代表实际值为 1.1001。

 

1.3.存储详解

#includeint main(void)
{
    float a = 10.5;   
    double b = 10.5;
    return 0;
} 

浮点数10.5转换为二进制为1010.1  利用公式转化1010.1  == gif.latex?%28-1%29%5E%7B0%7D*1.0101*2%5E%7B3%7D

故符号位 S = 0,指数位 E == 3,尾数位 M == 0101

float类型存入时指数位时加偏移值127,即存入130 (二进制:1000 0010)

01000 0010

010 1000 0000 0000 0000 0000

 十六进制:0x41280000

double类型存入时指数位时加偏移值1023,即存入1026 (二进制:100 0000 0010)

                                  

0100 0000 0010

0101  00000000 00000000 00000000 00000000 00000000 00000000

 十六进制:0x40250000 00000000

 用VS,验证变量a的内存存储情况正好为0x 41280000

 用VS,验证变量b的内存存储情况正好为0x 40250000 00000000

 

 

2.类型强制转换

2.1.指针类型强转

(1)int  ----->  float

#includeint main(void)
{	
	int a = 10;
	float* f = (float*)&a;
	
    printf("%f",*f);
	return 0;
}

1. 整形数据在内存中以补码的方式存储,变量 a 为整型占4字节,32比特,

    且10的补码为      00000000000000000000000000001010 ,

故10在内存中的存储方式如下图

 2.程序只对地址进行了类型转换,内存地址内保存的内容保持不变,仍然为整数10,由于float 类型与int 类型在内存中均占32个字节,所以通过 float *类型指针访问32比特内存恰好是变量a所在的32比特,编译器就会按照 float 类型的存储格式解释内存中的值;

 

 此时  S = 0,E = -127, M = 1.000 0000 0000 0000 0000 1010

 故    

  gif.latex?f%20%3D%20%28-1%29%5E0*1.000%200000%200000%200000%200000%201010*2%5E%7B-127%7D%3D0

因此程序输出结果为0.000000

 

 (2). float ---> int

#includeint main(void)
{
	float a = 10.5;
	int* p = (int*)&a;
	printf("%d", *p);
	return 0;
}

 a 在内存中存储结构如下图:

 

 

 通过int * 类型指针访问变量a所在的32比特,编译器就会按照int 类型的存储格式解释内存中的值;

因为符号位为0,所以这32bits被解释为整数,即

    01000001001010000000000000000000B = 1093140480D

 

 

 经过vs环境运行,结果与上文分析一致

 

2.2.变量类型强转

(1).int --->float

#includeint main(void)
{
	int a = 1234567890;			
	float f = (float)a;
	printf("%f", f);
	return 0;
}

 

整型1234567890 的二进制补码为

 将int 类型 转换成 float 类型即将a的补码当作浮点数存入内存,如下图

此时           gif.latex?X%3D%20%28-1%29%5E%7B0%7D*1.00100110010110000000101101001*2%5E%7B30%7D

 S= 0,E= 30 ,M= 1.00100110010110000000101101001

又因为float类型的位数部分只有23bits,故多余部分会被舍弃,只保留23位,第24位为1进1,否则舍去。得到 M =  1.001 0011 0010 1100 0000 0110

S,E,M,按规则存入内存

 

当float类型数据输出时,得到S= 0,E= 157-127=30,M = 1.001 0011 0010 1100 0000 0110

gif.latex?X%3D%20%28-1%29%5E%7B0%7D*1.00100110010110000000110*2%5E%7B30%7D%20%3D%201001%200011%200010%201100%200000%200110%200000%20000

转化为十进制为1234567936.000000

 经过vs运行检验,与理论数据一致

(1).float ---> int

#includeint main(void)
{
	float a = 12.5;
	int b = (int)a;
	printf("%d", b);
	return 0;
}

由前面内容可计算出12.5 在内存中的存储为

 

        

 

强转为int 时将其从内从取出:1010.1 去掉小数部分,将整数部分(1010)存入int型内存单元

 故通过%d输出时输出为12