数据在内存中的存储

文章详细解释了计算机中数据如何以补码形式存储,区分了大端和小端模式。讨论了整型数据(包括原码、反码和补码)以及浮点数(如float和double)在内存中的表示方式,遵循IEEE754标准,并通过一个示例展示了不同类型数据间的转换可能产生的效果。
摘要由CSDN通过智能技术生成

一、大小端的理解

        数据在计算机中都是以补码的形式存储的,大端模式的定义为将数据的低位保存在高位地址中,将数据的高位保存在低地址中。小端模式的定义为将数据的低位保存在低地址中,将数据的高位保存在高地址中。例如如果我要储存一个10,10的原码为0000 0000 0000 1010,反码0111 1111 1111 0101,补码0111 1111 1111 0110。

  

二、整型数据在内存中的存储

1、原码、反码和补码的介绍        

        数据在计算机中都是以二进制的形式存储的,计算机中的整数有三种表示方式, 分别是原码,反码和补码。原码存放的就是数据本身,正数的原码,反码和补码都是相同的,负数的反码和补码要通过原码计算出。具体的计算过程是原码符号位不变,其余位按位取反得到反码,反码+1得到补码。如果倒过来有了补码怎么知道原码呢,倒着推当然可行,将补码-1之后按位取反即可,但是其实还有一种算法,按照同样的步骤,将补码符号位不变其余位按位取反然后+1也可以得到原码,因为原码求补码的过程和补码求原码的过程算法一样,计算机运算时可以通用一个算法,从而大大提高效率。

  2、整型数据在内存中是以补码的形式,具体是大端模式还是小端模式可以通过观察字在内存中的顺序来判断。数据的补码是先以一个int类型也就是32个bit位存放然后根据变量类型发生截断或者提升。整型家族包括 char   short   int   long   long long,因为所占的内存空间的不同,取值范围也是不同的,规定它们取值范围的头文件为 <limits.h> 不同的类型原理都是相同的,为了方便研究,我们主要研究 char 类型。

        char 类型的变量占一个字节的空间,也就是八个比特位,可以存放的数据从 00000000 到 11111111 , char 类型包括 signed char  和 unsigned char ,对于 signed char  来说,这个八个比特位的最高位为符号位,剩下的七个比特位表示数据的实值,取值范围为 -128~127。对于 unsigned char  来说因为不存在符号位,所以这八个比特位全部用来表示实值,取值范围为0~255。

三、浮点数在内存中的存储

        浮点数包括 float  double  long double,它们精度不同,规定不同浮点数精度的头文件为 <float.h>。为了便于研究我们主要探究 float 和 double 类型,根据  IEEE 754  的标准规定,每一个二进制浮点数都可以表示为 (-1)^S * M * 2^E。S表示浮点数的正负,M表示这个用科学计数法表示这个二进制浮点数的有效数字,大于1小于2。E表示用科学计数法表示二进制浮点数时的指数位。因此我们要存储一个浮点数,只需要先将其表示为二进制浮点数,然后存储  S M E  这三个参数。不同的浮点数类型存放方式不同。

        对于32位浮点数,也就是float类型来说,占用4个字节也就是32个比特位,首先最高位位存放S,然后的八个比特位存放E,后面的23个比特位用来存放M。对于64位浮点数来说,占用8个字节,也就是64个比特位,最高位存放S,后面的11个比特位存放E,剩下的52个比特位存放M。

        S的取值只有0和1,S取0即为正,区1即为负。E的数据类型为unsigned int  但是我们在实际中二进制浮点数表示成科学计数法的指数位可以是负数,所以我们需要修正这个数据, IEEE 754  规定E为二进制浮点数的指数加上127(如果是64位浮点数修正就加上1023)。对于M来说,因为M的最高位必然为1,所以我们为了提升精度选择舍弃这一位,让这八位都表示实值,实际运算时再在最高位加上一个1。如果E全为0或者1,则运算方法不同。  E全为0时,浮点数的指数E等于1-127(或者1-1023)即为真实值, 有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于 0的很小的数字。  E为全1时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);

举一个例子  

        

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;
}

第一个 printf("n的值为:%d\n",n); 很简单,就是n的值,就是9。

第二次 printf("*pFloat的值为:%f\n",*pFloat); 时,因为是按照%f打印,9的补码是00000000  00000000  00000000  00001001,读取数据时候就认为它是float格式,最高位是0,所以是正数,后面8位都是0,E的真实值为  1-127= -126。M的值为1.00000000000000000001001,所以还原为浮点数为  (-1)^0*0.00000000000000000001001*2^(-126)。这个数字非常接近0,按照%f的精度是0.000000。后面*pFloat = 9.0,9.0可以写为1001.0。就是  (-1)^0*1.001*2^(-3),S的值为0,E的值为-3+127=124,换算成二进制就是01111100M的值为00100000000000000000000。在内存中不考虑大小端的存放的话是00111110000100000000000000000000,按照%d的读取的话是一个很大的正数。按照%f读取的话自然就是9.000000。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值