💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] # 内存的概念 ## 内存 程序和数据平常存储在硬盘(硬盘是一种可记忆盘)等存储器上,不管你开机或关机了,它们都是存在的,不会丢失。 硬盘可以存储的东西很多,但其传输数据的速度较慢。所以需要运行程序或打开数据时,这些数据必须从硬盘等存储器上先传到**另一种容量小但速度快得多的存储器**(无记忆盘),之后才送入CPU进行执行处理。 这中间的存储器就是内存。 **每个数据,都需要在内存上有其映射地址**。内存是如何进行编址,那属于操作系统。 ## 计算机内存 开启电源,启动BIOS,CPU工作,调用内存,内存跟硬盘索要资源 当你点击一个文件的时候数据经过数据总线传达到CPU,CPU发送指令到内存,内存那里会跟硬盘沟通,问他有没有这个东西,他说有,你就会看到这个文件夹里面是什么东西。 RAM 是随机存取存储器,它的特点是易挥发性,掉电即失。`妈蛋,难怪一断电,我的东西没保存,就找不到了` 既然内存是用来存放当前正在使用的(即执行中)的数据和程序,那么它是怎么工作的呢?我们平常所提到的计算机的内存指的是动态内存(即[DRAM](http://baike.baidu.com/view/3312702.htm)),动态内存中所谓的“动态”,指的是当我们将数据写入DRAM后,经过一段时间,数据会丢失,因此需要一个额外设电路进行[内存刷新](http://baike.baidu.com/view/329588.htm)操作。 具体的工作过程是这样的:一个DRAM的[存储单元](http://baike.baidu.com/view/1223079.htm)存储的是0还是1取决于电容是否有[电荷](http://baike.baidu.com/view/63129.htm),有电荷代表1,无电荷代表0。但时间一长,代表1的电容会放电,代表0的电容会吸收电荷,这就是数据丢失的原因。刷新操作定期对电容进行检查,若电量大于满电量的1/2,则认为其代表1,并把电容充满电;若电量小于1/2,则认为其代表0,并把电容放电,藉此来保持数据的连续性。 * * * * * * ROM(只读存储器或者固化存储器) * RAM(随机存取存储器) ROM和RAM指的都是半导体存储器,ROM是Read Only Memory的缩写,RAM是Random Access Memory的缩写。ROM在系统停止供电的时候仍然可以保持数据,而RAM通常都是在掉电之后就丢失数据,典型的RAM就是计算机的内存。 ### 为什么计算机内存,硬盘能存储数据 硬件技术是不断发展的,所以,只能说下基本原理:磁碟的表面有很多微小的小颗粒,能够被磁化。利用消磁和磁化原理来标识数据。 1字节,有8位二进制,一个字节能表示 255 个值(0000 0000 ~ 1111 1111 ) **程序要执行,首先将文件加载到内存中。 内存的每一个区域是有内存地址的,一个内存单元为一个字节。 程序加载到内存中,就会占用一部分区域,这一部分区域就是使用内存单元的范围来标识的。** ### 内存的存储原理 内存,英文名为RAM(Random Access Memory),全称是随机存取存储器。主要的作用就是存储代码和数据供CPU在需要的时候调用。但是这些数据并不是像用木桶盛水那么简单,而是类似图书馆中用有格子的书架存放书籍一样,不但要放进去还要能够在需要的时候准确的调用出来,虽然都是书但是每本书是不同的。对于内存等存储器来说也是一样的,虽然存储的都是代表0和1的代码,但是不同的组合就是不同的数据。让我们重新回到书和书架上来。 如果有一个书架上有10行和10列格子(每行和每列都有0~9编号),有100本书要存放在里面,那么我们使用一个行的编号和一个列的编号就能确定某一本书的位置。如果已知这本书的编号36,那么我们首先锁定第3行,然后找到第6列就能准确的找到这本书了。 在内存中也是利用了相似的原理现在让我们回到内存上,对于它而言数据总线是用来传入数据或者传出数据的。因为存储器中的存储空间是如果前面提到的存放图书的书架一样通过一定的规则定义的,所以我们可以通过这个规则来把数据存放到存储器上相应的位置,而进行这种定位的工作就要依靠**地址总线**来实现了。 对于CPU来说,内存就像是一条长长的有很多空格的“线”,每个空格都有一个唯一的地址与之相对应。如果CPU想要从内存中调用数据,它首先需要给地址总线发送地址数据定位要存取的数据,然后等待若干个时钟周期之后,数据总线就会把数据传输给CPU。当地址解码器接收到地址总线送来的地址数据之后,它会根据这个数据定位CPU想要调用的数据所在的位置,然后数据总线就会把其中的数据传送到CPU。 CPU在一行数据中每次只是存取1个字节的数据。回到实际中,通常CPU每次需要调用64bit或者是128bit的数据(单通道内存控制器为64bit,双通道为128bit)。 如果数据总线是64bit的话,CPU就会在一个时间中存取8个字节的数据,因为每次还是存取1个字节的数据,64bit总线将不会显示出来任何的优势,工作的效率将会降低很多。 这也就是现在的主板和CPU都使用双通道内存控制器的原因。 ## 地址总线、数据总线,控制总线。 ### 基本理解 在计算机内部每个有效信息,必须具有**3个基本属性:内容,指向,行为** 这三个属性要通过先个总线实现:数据总线,地址总线,控制总线。 好比:一封信件的内容、地址和信件状态,比如一封信到你家门口,邮递员大喊一声:“二狗子,你的信来了!”。 在计算机内部数据在**数据总线**上传递,每条传输线我们称之为1位,各个传输线按序排列他们之间是并行关系。 **地址总线**也是一样的,数据总线决定每次传输数据的大小,地址总线决定cpu所能访问最大内存空间大小。 **控制总线**反映了数据的状态和传输方式,它是地址总线的扩展补充。 ### 比喻 用经十路和经十路路边的单位数来对数据总线和地址总线宽度进行介绍: 2003年,济南市开始经十路的拓宽,由原来的双向4车道,拓宽为双向8车道 从通行能力上看,8车道显然比4车道通行能力强——也就是,一次通行的车辆比4车道多。因此经十路车道的宽度,就好比计算机中数据总线的宽度,数据总线越宽,计算机一次处理的数据就越多! 经十路沿线有很多单位,需要对沿街单位进行编号,如山东大学千佛山校区为经十路73号。在2000年时,沿街单位不过1000家,因此用0~999就可以对所有单位编号,但经十路拓宽后,带动了沿街经济的发展,后来有盖了很多楼,增加了很多单位,假设现在增加到1万家,那么单位编号就需要0~9999才能实现对所有单位的编号。 从上面看,对1000家单位,只需要号牌能装三位数字即可,假定单位号牌规定了每个数字的大小,则三位的号牌就只能编址到999,最多1000家单位。而对于1万家单位,则需要4位的号牌! 这里号牌所能装的数字的多少,就好比地址总线的宽度——地址总线越宽,它能编址访问的内存空间就越大,这里内存空间就好比沿街单位,若内存空间超过了编址的范围,就像1万家单位超过了3位号牌的编址范围,则多出去的空间,就没法编址进行访问了! ## 内存中的数据 数据在内存中始终是以二进制形式存放的。 1. 数值是以补码表示的。 2. 整型: 一个正数的补码和其原码的形式相同。而负数的补码方式是将其绝对值的二进制形式“按位求反再加1” 3. 实型: 在内存中占4个字节,是按照指数形式存储的,实型数据分为小数部分和指数部分,分别存放!计算机用二进制表示小数部分,用2的幂次来表示指数部分! 4. 字符型: 在内存中字符的存储实际上是把字符相对应的ASCII代码放到存储单元中的。而这些ASCII代码值在计算机中也是以二进制形式存放的。这个与整型的存储很相似。因此这两类之间的转换也比较方便! 5. 字符数据 系统在表示一个字符型数据时,并不是将字符本身的形状存入内存,而只是将字符的ASCII码存入内存。在内存中所有的数据又是以二进制的形式存放的。例子中'c1'、'c2'在内存中的表示如下: ![](https://box.kancloud.cn/73f101e46aa9d0fbda4f3f735756ae9d_208x185.png) 'c1'、'c2'的ASCII码为97、98。而97、98的二进制形式为`01100001`、`01100010`。 所以'c1'、'c2'在内存中的表示为 `01100001`、`01100010`。 ## 内存地址 内存地址空间是用16进制的数据表示, 如`0x8049324`, 那为什么需要用十六进制表示呢? 十六进制的意义何在? 编程中,我们常用的还是10进制.毕竟C/C++是高级语言。    比如:`int a = 100,b = 99`;    不过,由于数据在计算机中的表示,最终以二进制的形式存在,所以有时候使用二进制,可以更直观地解决 问题。但二进制数太长了。比如int 类型占用4个字节,32位。比如100,用int类型的二进制数表达将是: ~~~ 0000 0000 0000 0000 0110 0100 ~~~ 面对这么长的数进行思考或操作,没有人会喜欢。因此,C,C++ 没有提供在代码直接写二进制数的方法。用16进制或8进制可以解决这个问题。因为,进制越大,数的表达长度也就越短。 **不过,为什么偏偏是16或8进制,而不其它的,诸如9或20进制呢?** 2、8、16,分别是2的1次方,3次方,4次方。这一点使得三种进制之间可以非常直接地互相转换。8进制或16进制缩短了二进制数,但保持了二进制数的表达特点。 ### 十六进制表示 十六进制的意义: 1. 用于计算机领域的一种重要的数制    2. 对计算机理论的描述,计算机硬件电路的设计都是很有益的。比如逻辑电路设计中,既要考虑功能的完备,还要考虑用尽可能少的硬件,十六进制就能起到一些理论分析的作用。比如四位二进制电路,最多就是十六种状态,也就是一种十六进制形式,只有这十六种状态都被用上了或者尽可能多的被用上,硬件资源才发挥了尽可能大的作用。    3. 十六进制更简短,因为换算的时候一位16进制数可以顶4位2进制数。 十六进制的表示: C语言、Shell、Python语言及其他相近的语言使用字首`0x`,例如`0x5A3`。开头的`0`令解析器更易辨认数,而“x”则代表十六进制(就如`O`代表八进制)。在`0x`中的`x`可以大写或小写。 ### 十六进制内存地址 一个内存地址存着一个对应的值, 内存就相当于`(addr,val)`的大hash表,c语句的语义基本就是改变hash值。 如 `int i = 3`; 假设 `i` 的内存地址为 `0x8049320` ,那么这句话的语义是`0x8049320 = 3`,经过`i = 3`后,`i`为`(0x8049320,3)` 如 `int b = i`; 假设 b的内存地址为 `0x8049324` ,那么这句话的语义是`0x8049324 = i`对应的`val = 3`,此时`b`为`(0x8049324,3)`