整型在内存中的存储情况
通过学习,我们知道,整型数据在内存中存入的是该数据二进制的补码
对于正整数而言原码、反码、补码相同;
对于负整数而言 反码==原码按位取反、补码==反码+1;
例如:
正整数:
int a = 20;
20的原码为:00000000 00000000 00000000 00010100
负整数:
int b = -20;
-20的原码为:10000000 00000000 00000000 00010100
反码为:11111111 11111111 11111111 11101011
补码为:11111111 11111111 11111111 11101100
整型数据的第一位数据是用来存放符号位的
1为负数;0为正数
整型有32个bit,1位为符号位;其余都是有效位;
那么浮点型呢?
我们通过几行代码测试一下;
int a = 20;
printf("%d\n", a);
float* b = (float*)&a;
printf("%f\n", *b);
*b = 9.0f;
printf("%d\n", a);
printf("%f\n", *b);
首先将我们的变量a放入一个浮点型指针中,然后再利用解引用操作符打印出来,来对比相同数值,但不同类型的数据;
发现,数值根本就不相同
再通过解引用操作符修改a中的值为9.0的浮点型数据;
修改后的两组数据根本就是天壤之别;
那么为什么会出现这种情况呢?
原因就在于:浮点型数据与整型数据在内存中的存储情况是不同的
那么两者之间又有什么区别呢?
它又是如何表示的呢?
现在,就由我来讲解一下:
浮点型在内存中的的存储情况(本次介绍的是float(单精度浮点型)):
V = (-1)^S * M * 2^E
其中各个变量的含义如下:
- S:符号位,取值 0 或 1,决定一个数字的符号,0 表示正,1 表示负
- M:尾数,用小数表示,例如前面所看到的 8.345 * 10^0,8.345 就是尾数
- E:指数,用整数表示,例如前面看到的 10^-1,-1 即是指数
但我们知道数据在内存中存放的是一个个二进制序列,所以
尾数表示就变为了1.xxxxxxx,二进制表示中不会出现除0、1之外的数字
指数位也有所不同;因为它是二进制的缘故所以就表示为2^x;x是指数
用图像表示 float(单精度浮点数):
并且这三块区域都有不同的存法和取法;
符号位S:0表示为正数;1表示为负数,对应表达式(-1)^S
指数位E(E不全为0和E不全为1):指数位中规定存储进去的是unsigned int 类型(无符号整型);单精度浮点数有8个bit来存放E;所以E的取值范围就是0~2^8-1(0~255);缘于它有点庞大的取值范围;在存入的时候规定指数的真实值要加上一个中间值再存入;float(+127) double(+1023);取出的时候再减去这个中间值就可以了。
尾数部分M:我们知道;十进制的数字用科学计数法表示就是:x.xxxx*10^x;那么浮点数就表示为:1.xxxx*2^x;又因为二进制中如果用科学计数法表示的话,那么就都会写成1.xxxxx这样的数字;尾数部分就规定,在存入尾数位时舍去小数前面的1,只存后面的小数部分,这样做,就不会因为多存那个1而降低精度,也不会影响数值,取出的时候再加上那个1就没什么问题了。
E的另外两种情况
E为全0:在读取内存中的浮点型数据时,如果指数位为全0时;思考一下;此时的E是在加上了中间值(float+127)(double+1023)的数值;那么E的真实值就是0-127=-127;若一个数字写成±1*1.xxxx*2^-127的形式,它就是一个无限接近于0的数值;所以规定若某个浮点型在内存中存入的E为全0时,指数位统一表示为1-127=-126。
E为全1:指数位为全1时;说明它在存入时加上了中间值后为全1;真实值还原等于255-127=128;若一个数表示成±1.xxx*2^128的形式,那么它就是一个正负无穷大的数值。
介绍了这么多;不妨举个例子,说明一下;
举列子说明(5.5)
比如:5.5它是怎么存入内存当中的
一步一步的将5.5拆解,存入不同的区域当中
5.5用二进制表示为:101.1
记为:1.011*2^2
5.5为正数
符号位为:0
指数位2+127 为 129:10000001
小数位丢弃1.011中小数前的1 为:01100000000000000000000
综合下来,5.5存入到内存中的二进制序列为:0 10000001 01100000000000000000000
内存中的表示为:00 00 b0 40(小端机器下的内存显示)
回归到开头的那几行代码:
int a = 20;
printf("%d\n", a);
float* b = (float*)&a;
printf("%f\n", *b);
*b = 9.0f;
printf("%d\n", a);
printf("%f\n", *b);
现在通过一步步介绍,我们了解到整型和浮点型存入内存的存储方式不同,那么如果硬要以浮点型的方式打印整型数据和以整型方式打印浮点型数据,就会以不同类型的存储方式,读取内存中的值,打印出不同的结果;
20的二进制序列:00000000 00000000 00000000 00010100
若以浮点型的形式打印
内存中读取时就会将整型的二进制序列划分区域
:0 00000000 0000000 00000000 00010100
此时表示的就是一个0.000000这样的数字;
将浮点型9.0的数据存入再以整型方式打印时
9.0表示为 :1.001*2^3
内存中的表示情况为:0 10000010 00100000000000000000000
以整型存储方式读取时合并三块区域
:01000001000100000000000000000000
打印出的数值为:1091567616
希望本次的介绍能够对你有所帮助!