整数和浮点数在内存中存储

本文详细解释了整数(包括有符号和无符号)和浮点数在内存中的存储机制,通过示例代码展示了原码、反码和补码的区别,以及浮点数的IEEE754标准。
摘要由CSDN通过智能技术生成

整数在内存中的存储

 首先我们要知道 整数的2进制表⽰⽅法有三种,即原码、反码和补码

三种表⽰⽅法均有符号位和数值位两部分,符号位都是⽤0表⽰“正”,⽤1表⽰“负”,⽽数值位最 ⾼位的⼀位是被当做符号位,剩余的都是数值位。

正整数的原、反、补码都相同。

负整数的三种表⽰⽅法各不相同。

原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。

反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。

补码:反码+1就得到补码。对于整形来说:数据存放内存中其实存放的是补码。

#include <stdio.h>
int main()
{
 char a= -1;
 signed char b=-1;
 unsigned char c=-1;
 printf("a=%d,b=%d,c=%d",a,b,c);
 return 0;
}

我认为通过几段代码分析可能会更加好理解整数是如何在内存中存储的

看上面那段代码

1.首先我们要知道char 是占一个字节,八个bit位,而signed是修饰的有符号的,unsigned是修饰的无符号的,至于char是有符号还是无符号是取决于编译器的,而vs中是修饰的有符号的

2.所以char a类型可能存放的所有二进制序列有00000000 00000001 00000010.......10000000 10000001 10000010....11111110 11111111,这里所有的可能性有2的8次方种可能性即256种可能性

3.signer char就可以根据所学知识来分析了 最高位为符号位 0代表正数 1代表负数 剩下的七位为数值位,而内存中存的数据是补码,0开头的读取的是正数,正数的原码、反码、补码都相同,所以0开头一直到1开头为止他们的原码为0 1 2 3 4 5......126 127;剩下的1开头的如何分析呢,首先符号位为1代表负数,而我们假设已知补码是11111111,由原码等于反码+1可知,取反(符号位不变)10000000 +1后为10000001(得到原码)为-1,所以以此类推可得-1 -2 -3.......-127 -128。所以有符号类型的取值范围为-128~127

4.unsigned char 无符号位就显而易见了,00000000没有符号位,8个都是数值位,所以依次是0 1 2 3 4......254 255 ,所以unsigned char的取值范围为0~255

分析了这些基础知识后,我们来对这段代码进行解读

char a=-1

-1是个整数,放在变量a中,里面的二进制序位为32个bit位10000000000000000000000000000001 10000000000000000000000000000001这个是-1的原码,而在内存中的是补码为11111111111111111111111111111111,但是char是字节类型只能存放8个bit位即11111111

signed char b=-1与上同理,b存入的是11111111

unsigned char c=-1可能会有疑问担心不是说是unsigned的范围是0~255吗,但这里我们不用考虑,先给c存入-1去计算,c存入的也是11111111

但是存入后通过a,b,c前面所修饰的类型导致他们所对应的就会有不同

首先a=%d打印,是打印的一个有符号的整数,但是a是一个字符,不相符合,所以要提升后再打印,整形提升要补符号位,所以提升后a为11111111111111111111111111111111,这是补码,而%d是打印的原码,所以它的原码又变成了10000000000000000000000000000001  即   -1

b=%d与上文a的打印方式同理

c=%d这个就有区别了,11111111是无符号char提升的话要补0,则为00000000000000000000000011111111,%d打印有符号的整数,此时0代表正数,正数的原码、补码 、反码都相同,所以打印出来为255

此代码打印出来的结果就是-1 -1 255。通过这个题就可以然我们对整数在内存中如何存储有个很好的了解

#include <stdio.h>
int main()
{
 char a = -128;
 printf("%u\n",a);
 return 0;
}

接着再来分析一道

首先需要记住的是%u不同于%d,%u打印的是个无符号的整数

简要分析一下,char a中存放的是10000000(计算后),然后进行整形提升,char有符号补1,即11111111111111111111111110000000,而%u打印的是无符号整数,所以开头的1视为数值位,不存在原码、反码、补码的问题,即原码补码反码相同所以直接打印这个数(一看就非常大了),结果也是个很大的数。

接下来我们看浮点数在内存中的存储

V   =  (−1) ^S *M*2 ^E

(−1) ^S表⽰符号位,当S=0,V为正数;当S=1,V为负数

 M表⽰有效数字,M是⼤于等于1,⼩于2的

 2^E 表⽰指数位

举个例子十进制的5.5

5.5将其转换为二进制为101.1,用科学计数法表示为1.011,1.011*2^2

V=(-1)^0*1.011*2^2,S=0,M=1.011

对于32位的浮点数,最⾼的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数字M,浮点数的存储存储的就是S,M,E相关的值

对于64位的浮点数,最⾼的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效数字M

IEEE754对有效数字M和指数E,还有⼀些特别规定。

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

⾄于指数E,情况就⽐较复杂 ⾸先,E为⼀个⽆符号整数(unsigned int) 这意味着,如果E为8位,它的取值范围为0~255;如果E为11位,它的取值范围为0~2047。但是我们知道,科学计数法中的E是可以出现负数的,所以IEEE754规定,存⼊内存时E的真实值必须再加上 ⼀个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。⽐如,2^10的E是 10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。

指数E从内存中取出还可以再分成三种情况

 E不全为0或不全为1  这时,浮点数就采⽤下⾯的规则表⽰,即指数E的计算值减去127(或1023),得到真实值,再将有效 数字M前加上第⼀位的1。 ⽐如:0.5的⼆进制形式为0.1,由于规定正数部分必须为1,即将⼩数点右移1位,则为1.0*2^(-1),其阶码为-1+127(中间值)=126,表⽰为01111110,⽽尾数1.0去掉整数部分为0,补⻬0到23位 00000000000000000000000,则其⼆进制表⽰形式为:

E全为0 这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第⼀位的1,⽽是还原为0.xxxxxx的⼩数。这样做是为了表⽰±0,以及接近于0的很⼩的数字。

E全为1 这时如果有效数字M全为0,表⽰±⽆穷⼤(正负取决于符号位s);

#include <stdio.h>
int main()
{
 int n = 9;
 float *pFloat = (float *)&n;
 printf("n的值为:%d\n",n);
 printf("*pFloat的值为:%f\n",*pFloat);
 *pFloat = 9.0;
 printf("num的值为:%d\n",n);
 printf("*pFloat的值为:%f\n",*pFloat);
 return 0;
}

通过这段代码来深入了解浮点数如何在内存中存储

1.int n=9;9的二进制序列为00000000 00000000 00000000 00001001(此时n的空间所存储),以整数的形式存,又以整数的形式取出,第一个代码打印为9

2,取n的地址存入pFloat里面,在pFloat的角度看待其是浮点数的存储,其会这样解读这32个bit位,0 00000000 00000000000000000001001,三段分别为S M E,当内存中E为全零时,真实的E为1-127=-126,有效数字M不会再加上1,取出后0.0000000000000000001001  所以存储的值为(-1)^0*0.0000000000000000001001 *2^-126;%f默认打印小数点后六位,这个值非常小所以只能打印出0.000000

3.*pFloat,将pFloat解引用得到这块整形空间存储的00000000 00000000 00000000 00001001,以浮点数的视角存储9.0(10)二进制1001.0     1.001*2^3 (-1)^0*1.001*2^3 S=0,M=1.001,E=3存入E3+127=130   0 10000010 00100000000000000000000(此时n的空间所存储),接下来以整数的形式去取出来,首先存的是补码,其次%d是存储的有符号,0为正数,原码、反码、补码都相同,直接打印出值1091567616

4.浮点数存储,浮点数取出,打印出来为9.0

上述就是有关整数和浮点数在内存中的存储

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值