首页 > 系统相关 >数据在内存中的存放

数据在内存中的存放

时间:2023-06-30 20:56:01浏览次数:52  
标签:00 0000 补码 存储 1111 存放 内存 数据

1.整形变量在内存中的存储

  • 原码、反码、补码

计算机中整数都是以二进制进行存储的。其中有三种表示方法:原码,反码与补码。他们分为符号位、数值位两部分。计算机中存储的是补码形式。

规定符号位用0表示正,用1表示负。

  • 原码:直接将二进制按照正负数的形式翻译成二进制即可。
  • 反码:原码符号位不变,其它位依次按位取反。
  • 补码:反码 末位 +1 得到补码。

补码转换成原码:对补码进一步求补码,即符号位不变,数值位取反,末位再加1。

规定正数的原码、反码、补码相同。负数的三码之间转换使用上面的方法。为什么计算机中存储的是补码形式呢?

使用补码形式,可以将符号位和数值域统一处理。同时加法和减法也可以统一处理(CPU)只有加法器,此外补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

示例代码:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i = -1;  
    int j = 10;
    int ret = i + j;
    printf("i = %d\n",ret);
    
    exit(0);
}

首先,需要确定该编译器中内存对数据的存储方式是大端存储还是小端存储

//定义十六进制数a
int a = 0x11223344   // 数据地位:高位 --> 低位
0x0000008B34FEFA24  44  // 内存低地址(存储低位数据)
0x0000008B34FEFA25  33  //     |
0x0000008B34FEFA26  22  //     V 
0x0000008B34FEFA27  11  // 内存高地址(存储高位数据)

可见该内存对数据的存储是小端存储。

// i = -1 的地址以及在内存中的表示 :
0x000000F1BD7CFA64  ff    // bin : 1111 1111
0x000000F1BD7CFA65  ff    // bin : 1111 1111
0x000000F1BD7CFA66  ff    // bin : 1111 1111
0x000000F1BD7CFA67  ff    // bin : 1111 1111
ff ff ff ff -> 1111 1111 1111 1111 1111 1111 1111 1111 (补码形式)
  (首位符号位) 1000 0000 0000 0000 0000 0000 0000 0000 (反码形式)
               1000 0000 0000 0000 0000 0000 0000 0001 (原码形式)
转换成十进制为 1 。

// j  = 10 的地址以及在内存中的表示 : 
0x000000F1BD7CFA84  0a    // bin : 0000 1010
0x000000F1BD7CFA85  00    // bin : 0000 0000 
0x000000F1BD7CFA86  00    // bin : 0000 0000 
0x000000F1BD7CFA87  00    // bin : 0000 0000  
00 00 00 0a -> 0000 0000 0000 0000 0000 0000 0000 1010 (补码形式)
正数的三码相同,因此转换成十进制为 10.

// ret 的地址以及在内存中的表示 : 
0x000000F1BD7CFAA4  09    // bin : 0000 1001
0x000000F1BD7CFAA5  00    // bin : 0000 0000  
0x000000F1BD7CFAA6  00    // bin : 0000 0000    
0x000000F1BD7CFAA7  00    // bin : 0000 0000   
00 00 00 09 -> 0000 0000 0000 0000 0000 0000 0000 1001
ret = 9 是正数,三码相同,转换成十进制是 10.

存储示意图:

image

计算机的位数也叫字长,是指处理器一次运算所能处理的二进制数的位数。

2.浮点数在内存中的存储

根据国际标准IEEE(电气和电子工程协会),任意一个二进制浮点数V可以表示成下面的形式:

(-1)^S \times M \times 2^E 
  • (-1)^s表示符号位,当s=0V为正数;当s=1V为负数。
  • M表示有效数字,大于等于1,小于2。
  • 2^E表示指数位。

浮点数转化为十进制,为各个位与位权乘积之和。以小数点为分界线,小数点前的位权依次是 2^0, 2^1 ···,小数点后的位权依次为2^-1, 2^-2···。详见下图:

以此类推。0次幂前面的位的位权 按照 1 次幂、2 次幂……的方式递增,0 次幂以后的位的位权按照-1 次幂、-2次幂……的方式递减。这一规律并不仅限于二进制数,在十 进制数和十六进制数中也同样适用。

例如5.5,因为二进制(5) = 0101,根据上面规则倒推:因为0.5 = 1 * 2^-1,则可知,(二进制)5.5 = 0101.1,写成科学计数法形式为:

\(1.011 \times 2^2 = (-1)^0 \times 1.011 \times 2^2\)

可知:S = 0, M = 1.011, E = 2.


所以它是如何进行存储的呢?

IEEE 754对有效数字(尾数部分)M和指数(部分)E,还有一些特别规定:

  • 1≤M<2,也就是说,M可以写成1.xxxxxx的形式,其中xxxxxx表示小数部分。 在计算机内部保存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是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数:
  • 对于8位的E,这个中间数是127;
  • 对于11位的E,这个中间数是1023。

比如,2^10E10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001

那么为什么内存对浮点数的存储要取中间数呢?为什么要取127、1023?

指数部分用的则是“EXCESS系统表现”,即通过将指数部分在相应精度下所能表示的最大范围的中间值设为0,使得负数就不需要单独进行表示,也就时用相对为负来表示负指数的情况的情况。就好比用1 ~ 13 这组数表示负数,其范围以确定,就把中间值7当作0,比如,10就表示+3,4表示-3.这个规则说的就是EXCESS系统. 因此:

  • 对于单精度浮点数类型数据,E最大值为1111 1111 -> 128+64+32+16+8+4+2+1 = 255,中间值为127
  • 对于双精度浮点数类型数据,E最大值为0111 1111 1111 -> 1024+512+256+128+64+32+16+8+4+2+1 = 2047,中间值为1023

示例一

 float f = 5.5;
 二进制形式:101.1
 正则表达式:(-1)^0 * 1.011 * 2^2
 符号值:S=0
 尾数值:M=1.011
 指数值:E=2 + 127 = 129 //实际在内存中存储的值
 0 10000001 01100000000000000000000  //存储的时候,有效数字省略小数点前的1,之后的有效数字在内存中从高为开始依次存储(011存进去后因为最终有23位所以后面补0)。

转换成内存空间中以十六进制保存为:

  • 以8bit为单位划分:0100 0000 1011 0000 0000 0000 0000 0000
  • 以8bit为单位实现小端存储:0000 0000 0000 0000 1011 0000 0100 0000
  • 十六进制: 0 0 0 0 b 0 4 0
  • 即 00 00 b0 40

示例二

float g = 0.75;
二进制形式:因为:0.75 = 0.5 + 0.25 = 2^-1 + 2^-2 -> 所以:0.11 
 正则表达式:(-1)^0 * 1.1 * 2^-1
 符号值:S=0    //0
 尾数值:M=1.1  //100000000000000000000000
 指数值:E=-1 + 127 = 126 //实际在内存中存储的值: 01111110
 0 01111110 100000000000000000000000

转换成内存空间中以十六进制保存为:

  • 以8bit为单位划分:0011 1111 0100 0000 0000 0000 0000 0000
  • 以8bit为单位实现小端存储:0000 0000 0000 0000 0100 0000 0011 1111
  • 十六进制: 0 0 0 0 4 0 3 f
  • 即 00 00 40 3f

image

你滴明白?明白!

标签:00,0000,补码,存储,1111,存放,内存,数据
From: https://www.cnblogs.com/jxsme/p/17517799.html

相关文章

  • 【一】MySQL数据库之引入
    【一】MySQL数据库之引入【一】数据库管理软件的由来基于我们之前所学,数据要想永久保存,都是保存于文件中,毫无疑问,一个文件仅仅只能存在于某一台机器上。如果我们暂且忽略直接基于文件来存取数据的效率问题,并且假设程序所有的组件都运行在一台机器上,那么用文件存取数据,并没......
  • 【二】MySQL数据库之下载安装
    【二】MySQL数据库之下载安装【1】Window系统(1)安装1、下载MySQLCommunityServer5.7.16http://dev.mysql.com/downloads/mysql/2、解压如果想要让MySQL安装在指定目录那么就将解压后的文件夹移动到指定目录如:C:\mysql-5.7.16-winx643、添加环境变量【右键......
  • 【四】MySQL数据库之MySQL语句初识
    【四】MySQL数据库之MySQL语句初识有了mysql这个数据库软件就可以将程序员从对数据的管理中解脱出来专注于对程序逻辑的编写mysql服务端软件即mysqld帮我们管理好文件夹以及文件前提是作为使用者的我们需要下载mysql的客户端或者其他模块来连接到mysqld然后使用mys......
  • 【三】MySQL数据库之MySQL软件基本管理
    【三】MySQL数据库之MySQL软件基本管理关于Linux版本的基本管理与破解密码详情:【1】登录,设置密码(1)初始状态下,管理员root,密码为空,默认只允许从本机登录localhost(2)设置密码[root@egon~]#mysqladmin-urootpassword"123"(3)设置初始密码由于原密码为空,因此-p可以......
  • 【五】MySQL数据库之库相关操作
    【五】MySQL数据库之库相关操作库相关操作【一】系统数据库information_schema:虚拟库不占用磁盘空间存储的是数据库启动后的一些参数如用户表信息、列信息、权限信息、字符信息等performance_schema:MySQL5.5开始新增一个数据库:主要用于收集数据库服务器性能参数......
  • 【七】MySQL数据库之记录相关操作
    【七】MySQL数据库之记录相关操作记录相关操作【一】介绍MySQL数据操作:DML在MySQL管理软件中,可以通过SQL语句中的DML语言来实现数据的操作,包括使用INSERT实现数据的插入UPDATE实现数据的更新使用DELETE实现数据的删除使用SELECT查询数据以及。本节内容包括:......
  • 【八】MySQL数据库之数据库IDE与pymysql模块
    【八】MySQL数据库之数据库IDE与pymysql模块数据库IDE与pymysql模块【一】IDE工具介绍生产环境还是推荐使用mysql命令行但为了方便我们测试可以使用IDE工具在此我们推荐使用Navicat软件或pycharm来连接数据库这样就能更详细直观地查询数据掌握:#1.测试+链接数据......
  • 大数据面试题集锦-Hadoop面试题(三)-MapReduce
    你准备好面试了吗?这里有一些面试中可能会问到的问题以及相对应的答案。如果你需要更多的面试经验和面试题,关注一下"张飞的猪大数据分享"吧,公众号会不定时的分享相关的知识和资料。目录1、谈谈Hadoop序列化和反序列化及自定义bean对象实现序列化?2、FileInputFormat切片机制3、......
  • 双写一致性之定时更新、异步发送短信、异步秒杀逻辑前后端、课程页页面前端、课程相关
    目录一、双写一致性之定时更新任务逻辑二、异步发送短信视图函数任务三、异步秒杀逻辑前后端1.1前端Sckill.vue视图类路由任务四、课程相关表分析先创建一个course.app表数据迁移表六、课程表数据录入七、课程主页接口一、双写一致性之定时更新任务逻辑@app.taskdefupdate......
  • 内存分配与回收策略
    内存分配与回收策略对象的内存分配,就是在堆上分配(也可能经过JIT编译后被拆散为标量类型并间接在栈上分配),对象主要分配在新生代的Eden区上,少数情况下可能直接分配在老年代,分配规则不固定,取决于当前使用的垃圾收集器组合以及相关的参数配置。以下列举几条最普遍的内存分配规则......