数据在内存中的存储

目录

整数在内存中的存储

内存的大小端

什么是大小端

纠正

次方序

不要直接对int 类型变量强转为char类型,不管是大端还是小端,转完后都可以保留一部分地位(int里面放的值不超过8位二进制数表示的的整数,就能被完全保留下来) 

有符号 char 和 无符号 char 

​编辑 char 的二进制补码突破

一个-1是如何存入 char 类型的。 

%d 打印无符号char 类型里面的-1

 char周期图(有符号)

 有符号char周期图

 浮点数在内存中的存储

最大数计算

计算公式

浮点数的具体存储 

规则表:

浮点数的存入 

浮点数的取出



整数在内存中的存储

整数在内存中存的是二进制补码,正数的 原、反、补码相同,负数的补码,由源码取反加一获得。

对于有符号整数,把最高位看作符号位。无符号整数,没有符号位,全表示正数

 对于整形,二进制里面存放的是二进制补码。


内存的大小端

什么是大小端

超过一个字节的数据在内存中就存在着顺序问题,一般分为大端和小端。

讨论的是字节的顺序。

大端字节序:地址存二进制数,地址存二进制数。

小端字节序:地址存二进制数,地址存二进制数。

在调试窗口中,为了方便观察,显示的是十六进制数,但本质依然是一个32位(int类型)的二进制数。

我自己的小疑惑解析:问题是为什么0x11223344就刚好放满呢?

答:二进制转16进制就是,每4位表示一个十六进制数,32位能表示8个,也就是说这个11223344,每一位都是一个十六进制数,每一位都需要4个二进制来放。所以能放满

而且顺序是倒过来的,这个图片就是n里面存放的二进制数。他存是这么存,转成十进制还是得从低址往高地址相加。只是把二进制数倒着放而已

0x11223344的二进制数本质还是,只不过倒着放在了VS的内存中。

纠正

大端和小端的本质是字节序,一个字节八位,每八位的倒着存放的

不完全是倒着存的,只有每个字节序是倒着放的,里面的二进制位可没有倒着

列如,0x12345678

 他的二进制位应该是,

那有什么用呢?

如果你想从监视窗口那直接由十六进制转十进制或者二进制,那么就得注意了

0x12345678在内存中举例

转十进制应该是 :

7*16(一次)+8*16(0次)+5*16(3次)+6*16(2次)+3*16(5次)+4*16(4)+1*16 (7次)+2*16(6)

次方序

0 1 3 2 5 4 7 6

不要直接对int 类型变量强转为char类型,不管是大端还是小端,转完后都可以保留一部分地位(int里面放的值不超过8位二进制数表示的的整数,就能被完全保留下来) 


有符号 char 和 无符号 char 

signed char ,规定:内存中最高位为符号位,有效数值位只有7位,

        也就是说 signed char 最大也就127,最小-128(7位二进制数最大能表示 2的7次方减一,127),把最高位看成正负号的话。

        我以为最小-127呢,结果有规定,1 0 0 0 0 0 0 0,为-128,按道理-128一个char 是存不下的

        他需要9位表示,-128补码按道理应为1 1 0 0 0 0 0 0 0,没办法这就么规定

而 unsigned char 8 位二进制全表示正数,最大为2的8次方减一,255

 char 的二进制补码突破

        也就是说,当127的补码再加一,0 1 1 1 1 1 1 1,变成1 0 0 0 0 0 0 0就会变成-128,再加一就是1 0 0 0 0 0 0 1 -127,突破正127后变成-128 ,补码再增加的话,这个负数也在增加,最终来到,1 1 1 1 1 1 1 1,也就是-1的补码。

        无符号的话突破就突破了,上限是255,1 1 1 1 1 1 1 1二进制补码。 再突破就是0了,因为放不下。

一个-1是如何存入 char 类型的。 

        首先,-1是一个整型,所以他的二进制为有32个,如图第一行,又因为一个数在二进制中存的是补码,所以转成补码是如图第三行,然后可以存了,又因存入的是一个char 类型,所以32位根本放不下,只取右边的8八位

%d 打印无符号char 类型里面的-1

 首先-1存在一个char内存中的补码是1 1 1 1 1 1 1 1,%d意思是以有符号整形的形式打印,所以补码1 1 1 1 1 1 1 1,先整形提升,根据原类型提升(如果是无符号数最高位补0,有符号数补符号位),如图第二行,然后%d再来判断,%d把这个补码看成有符号数,最高位是0,代表是个正数,此时就不需要转原码了,直接把这个二进位数当成整数打印出来。

         第一个圈为,计算-128的补码然后截断给到 char a

        第二圈为整形提升,提升完,由无符号整形打印,把整形提升完后的补码看作无符号整数

 char周期图(有符号)

 有符号char周期图

 浮点数在内存中的存储

范围头文件为:float.h ,整数范围文件在 limits.h

最大数计算

short类型最大数计算 ,short占2个字节,16个二进制位,最高位看成符号位舍去,有效位15位,在,最大数就等于2的15次方减一。   (其实你带进去的时候发现根本没有2的15次,最高是14,这里值得注意的是,从2的0次一直加到2的14次就等于2的15次方减一,就是最大数

计算公式

用计算器算时,小数点后一位,就是1除2(2的一次),第二位就是1除4(2的二次),第三位就是1除8(2的三次),以此类推。

        举例,float a = 6.6(我也是随便写,正边写边算呢),二进制位等于(无法精确写出)

     1、   0.1 这个1=2的负一次方,等于二分之一,也就是0.5 ,

     2、  0.11 等于 0.5 + 0.25(1除4) = 0.75 太大了所以舍去(第二个1就是2的负二次方)

     3、   0.101 等于 0.5 + 0.125(1除8) =0.625也太大

     4、  0.1001 等于 0.5+(1除16)2的负四次方,也就是十六分之一,等于0.0625,        0.5+0.0625=0.5625,太小继续往后添一个二进制1

     5、    0.10011等于 这里用分数逼近把感觉好算一点,0.6等于五分之三,二分之一+十六分之一+32分之一等于 32分之16+32分之2+32分之1=32分之19(感觉也不是很好算)还是靠计算器吧。0.5625+0.03125(1除32)=0.59375(很接近了)小了就在后面加一,大了就把你计算的这一位变0,在再后面添1看看是大还是小,大了变0看下一位。0.100111 =          6、   0.10011 + 0.000001(1除64)= 0.59375 + 0.015625 =0.609375,大了归0,再看后面的1

      7、   0.1001101 = 0.59375 + (1除128) 0.0078125 = 0.6015625

      8、  0.10011001 = 0.59375 + (1除256)0.00390625 = 0.59765625

      9、 0.100110011 = 0.59765625 + (1除512)0.00195312 = 0.59960938(2的负9次方了),最后那俩位38是375约等的手机没横过俩约等了,1除256那儿是对的

     10、  0.1001100111 = 0.599609375 + (1除1024)0.0009765625 = 0.6005859375.

     11、   0.10011001101 =  0.599609375 + (1除2048)0.00048828125 =0.600097656625

     12、    0.100110011001 =  0.599609375+(1除4096)0.00048828125 = 0.599853515625

     13、   0.1001100110011 =  0.599853515625 +(1除8192)0.0001220703125 = 0.5999755859375

     14、 0.10011001100111 = 0.5999755859375 +(1除16384)0.00006103515625 =0.60003662109375‘

这后面貌似规律一样了,等会儿可以猜着写一下具体的存储。float的有效位是23位

        110.100110011001100110011001101100(6.6的二进位猜写)下面会用

由此证明一个浮点数有可能无法再内存中精确保存。二的负14次方了已经

浮点数的具体存储 

规则表:


double 类型的区别,就在于是64个二进制位,S 占1个,E占11个,剩下52给有效数字M,所以他的精度更高。还有就是存E的时候加上1023

   

浮点数的存入 

    拿上面的6.6的二进制位举例。110.100110011001100110011001101100

首先,先转成一个小于2大于1的科学计数法的数,1.10100110011001100110011乘2的2次方

就能还原,这个2的2次方也是有用的。’

        然后咱们就来分析,谁是S 谁是 E 谁是 M,我们只需存这仨就行。

        S,第一位,只需要看存的这个数是正数还是负数就行,正数就是0,负数就是1

所以上面低二张图的第一个S就是 0

                0

        然后看E,这个E就是上面变成科学计数法法表示的二进制数乘的那个2的2次方,的指数2,存的时候有小细节,float类型给E的空间只有8位,其次这8位全当作无符号数识别(因为会有负数),规定:得到的指数必须要加127再存进去。所以E=129=10000001(图4)

E要点:也就是是说0~126,表示负数,127~255表示正数(指数),其实不难发现咱们一个14次已经非常非常精确了。

                0 10000001 (目前咱已经存了这些了)

        M,这儿也有细节,存的时候只存小数部分的二进制位(精度更高),也就是咱们只要

10100110011001100110011 这一坨

                0 10000001 10100110011001100110011 (ok大致就是我的猜想数,我也不确定他们是不是有规律的)咱们直接给他转成16进制然后去内存里面看一下。

                0100 0000 1101 0011 0011 0011 0011 0011 

                    4   0            D  3         3   3            3  3

        由此可以看见咱们还没走错,(倒着存的)放归倒着放不影响咱们的计算,和机器的识别。

浮点数的取出

一般来说,只需要把那两个小细节还回去就行了,

        0 10000001 10100110011001100110011,那它举例,

        10000001=129,减去127,等于=2=E=指数,

        10100110011001100110011,这一坨是小数,只要再前面加一个 1.  就行了

        1.10100110011001100110011 ,小数点再向右边移动两位,因为指数是正2如果算出来最后是负2就向左移动,110.100110011001100110011,再转十进制就行,不过这是近似值我就不算了。

有两个特殊点就是

E等于0(00000000)二进制位,规定真实指数为-126。不用纠结记就完了。

如果拿 1.10100110011001100110011,这个举例,在移动小数点的时候,还得向左移动126位,这得多小。

还原的时候还不用添1了。

和E等于255(11111111) 二进制位,指数为127,向右移动127位,非常大,然后看符号位,表示正负无穷大

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值