数据存储解释

目录

一背景:

二具体举例

三整数存储规则

四浮点数储存规则: 

   数据各部分存储如下:     


一背景:

  在我学到指针的时候,我知道指针类型默认就是它指向的类型,指针类型决定步长,步长换句话来说就是一次能访问的字节数,但是我突然发现,float*和int*的步长是一样的,那如果我把整型指针强制类型换为float*,然后去访问整型数据,又或者把浮点数指针强转为int*指针访问整数结果又会怎么样呢?

二具体举例

(1)如下代码

int n = 9;
	float* p = (float*)&n;
	printf("整型视角看待整数    : %d\n", n);
	printf("浮点数型视角看待整数  :%f\n", *p);
	*p = 9.0;
	printf("整型视角看待浮点数  :%d\n", n);
	printf("浮点数视角看待浮点数:%f\n", *p);

 

      在这个代码中我们可以发现,我们在一段内存中按整型存储存入了9,如果用浮点数视角看待这段内存(浮点数指针访问整型),我们用%f打印结果为零,而用整数视角看待用float类型存储的数,打印出来的值更是非常奇怪,这说明浮点数和整数看待同一段内存是不一样的,为了弄清楚这个问题,我们就要好好了解浮点数和整数在内存的存储规则。

(2)相似代码

    还有就是这个代码,千万要和举例1的代码区分好,我这里应该算是printf用%d打印%f,用%f打印%d的结果分析,一般一般不同类型的数据在赋值的时候  如果类型不一致 编译器会尝试进行隐式类型转换的,但是printf这里不会  如果类型不一致  无法解析了就按照解析失败处理  最后统一打印0了 举例1是用浮点数的角度解析整数9在内存的存储,以及反着来解析浮点数, 我还是好好讲解一般浮点数存储和整数存储的不同吧。

三整数存储规则

     整数的存储很简单,存储在内存的为数据的补码,数据分负数和正数,负数和正数在转为补码的时候略有不同。一般原反补关系如下:

       原码
       直接将数值按照正负数的形式翻译成二进制就可以得到原码。
      反码
      将原码的符号位不变,其他位依次按位取反就可以得到反码。

     补码
     反码+1就得到补码。

  (1)正数的补码:正数的原,反,补码都相等

  (2)负数的补码:负数的则需要上述原反补关系转换

四浮点数储存规则:

      是时候搬出规定了,根据国际标准,任何一个浮点数x(包括float类型和double类型)都可以写成下面的形式,

(-1)^s*m*2^E

(-1)^s表示符号位,当s锁存数为0时,x为正数;当s所存数为1时,x为负数。

M表示有效数字,大于等于1,小于等于2;

2^E表示指数位;

对于32位的浮点数来说,最高位为符号位s,接着的为八位指数E,剩下的23位为有效数字M

 双精度浮点数的储存和单精度浮点数是大同小异的

 数据各部分存储如下:     

1.M的存储:

前面说过,1≤M<2,也就是说,M可以写成1.xxxxxx的形式,其中xxxxxx表示小数部分。
IEEE754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。

2.E的存储

c语言规定E为无符号整型(至于为什么是无符号整型,我个人觉得如果E也有符号位,s也是符号位,对于计算机来说要处理两位符号位,这个时候对于计算机来说直接把负数转为正数要简单的多),所以当E为八位时,取值范围为0到255,当E为十一位时,取值范围为0到2047,可是就我们刚刚举例的5.5来看,E的值为-1,这个时候c语言的处理就是把E的值都加127再存放到内存中去,但是如果是-128+127,结果为-1(至于为什么是加127,而不是128呢?我觉得理解为选127使得数据正负范围分布更大就可以了,+128时范围为5.877*10^(-39)到1.7*10^38,+127时范围为1.175*10^(-38)到3.4*10^(38),人为规定的每个人都有觉得对的理由)

既然存储计算机做了许多处理,在取出数据的时候同样需要许多处理将其还原为真实的数据。

3.E的取出

这个就比较复杂了,但这也正是上代码运行结果的重要理论基础。

(1)当E不全为0或者不全为1时

此时把E转换为十进制然后减去127即可

(2)当E全为0时

这说明E本来是-127,这已经很小的数了,所以当我们取出M的时候就不补1了,而是补零。

(3)当E全为1时

这说明E是255,2的255次方,这是一个非常大的数,当M全为零时可以看做原来的数字是趋近正无穷或者负无穷,具体要看s的值。

4.代码解释:

当我们在内存中存入整形数据9时,转换为二进制为00000000 00000000 00000000 00001001,从浮点数的角度来看,S为0,E全为零,M为0000000 00000000 00001001,这个时候的E已经能说明这是个很小的数了,计算机将其视为0,故此时打印结果为0

当我们存入浮点数数据9.0时,首先9.0表示为1001=(-1)^0*1.001*2^3,所以此时E为3,加127存到转为二进制1000  0010存到内存中,S为0,M为1.001,数据存到内存中为,0   10000010(E)  00100000000000000000000(M),而对于整数来说,这个三十二位的二进制就是2^30+2^24+2^20=1073741824+16777216+1048576=1091567616.

 完结感言:当我们学了上面知识后,运用到实际上就可以大致知道储存一个数字是有极限的,也就可以更理智地看待拼夕夕的活动,只差零点1这都是套路(哈哈哈),接下来路还长着呢。终于又完成了一篇,很多时候我并不想钻研,因为那种越来越多问题出现不知道怎么解释的时候真的很折磨,好在都过来了,祝大家都能在探索的路上坚持下来。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小何只露尖尖角

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值