RAM

存储类型

计算机存储器可分为内部存储器(简称内存或主存)和外部存储器, 其中内存是 CPU 能直接寻址的存储空间, 由半导体器件制成. 内存的特点是访问速率快. 我们平常使用的程序, 如 Windows 操作系统, 打字软件, 游戏软件等, 一般都是安装在硬盘等外存上的, 但必须把它们调入内存中运行, 才能真正使用其功能, 我们平时输入一段文字, 或玩一个游戏, 其实都是在内存中进行的, 数据产生后不断地由内存向外存进行刷写. 就好比在一个书房里, 存放书籍的书架和书柜相当于计算机的外存, 而我们工作的办公桌就是内存. 通常我们把要永久保存的, 大量的数据存储在外存上, 而把一些临时的或少量的数据和程序放在内存上, 当然内存的好坏会直接影响计算机的运行速度.

  • 内存(英语: Random Access Memory,简称:**RAM**)是与 CPU 直接交换数据的内部存储器. 它可以随时读写(刷新时除外), 而且速度很快, 通常作为操作系统或其他正在运行中的程序的临时数据存储介质.
  • 外存(英语: Non-Volatile Memory,缩写:NVM)分为只读存储器(英语: Read-Only Memory, 简称: ROM)和快闪存储器(英语: flash memory, 简称闪存)
    • ROM: ROM 是一种半导体存储器, 其特性是一旦存储数据就无法再将之改变或删除, 且内容不会因为电源关闭而消失. 因此一般保存计算机的基本配置用于开机读取.
    • NVM: 广义称作闪存, 包括硬盘, 存储卡等.

理解 RAM

假设我们是 CPU, 现在我们有一个本子, 名字叫 RAM. RAM 有一百页, 每一页由10行*10列的单元格组成, 每个单元格可以最多容纳4个数位(二进制). 我们可以简单推断出以下关于 RAM 的特质:

  • 每格数字范围:
    • 最小: 0000 - 0 (十进制)
    • 最大: 1111 - 15 (十进制)
  • 每页最大范围: 10 * 10 * 4= 100 (数位)
  • 全部最大范围: 10 * 10 * 100 * 4 = 40,000 (数位)

我们的 I/O 设备是笔和格子, 通过笔输入, 通过格子输出.
在第一页第一行第一列写入 0000.
那么下次我们就知道我们在第一页的第一个格子写上了 0000, 我们以 页-行-列: 数据的形式表示,因此我们的输出是:

1-1-1: 0000

以此类推, 我们可以记满整个本子.
但是问题来了, 计数的范围之能事 0~15, 这肯定是不符合现实需求的. 那么怎么解决呢? 我们现在把相邻的两个格子连起来, 也就是以说原本一行的格子编号是:

| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |

现在的格子编号是:

| 1 | 2 | 3 | 4 | 5 |

原本只能表达:

0000 ~ 1111

0 ~ 15

现在能表达:

00000000 ~ 11111111

0 ~ 128

我们牺牲格子的数量, 增加单位格能表达的最大数长度, 这就是 RAM 用来表达大数的原理. 现实世界中, 一个存储单元就是 8 位二进制, 也就是一个字节(Byte). 而一个数位(bit)指的是二进制中 0 或 1.

  • Byte: 由于 Byte 是一个极小的单位, 现实中都是用 MB(Megabyte), GB(Gigabyte)等单位.

而我们读写的单元格(现在你知道他其实是存储单元), 寻找每一个存储单元的过程, 就叫寻址.

数据类型: 早期编程语言

诞生于早期的计算机语言, 比如 C. 由于早期的计算机性能过于孱弱. 要节省每一个存储单元. 如何做到呢? 依然是上面的把格子连接的方式, 不过这次不改变编号了, 我们还是以页-行-列: 数据的方式寻址, 但是这次我们加上需要的单元格数量, 也就是页-行-列-单元格: 数据.
假设我们要在第一页第一行第一列写下129, 我们就连起2个单元格, 位置就是:

1-1-1-2: 0000 0001 0000 0000

这样或许看起来有点浪费, 因为前面都是 0, 但是别忘了, 我们现在的最小单元格是 8 个数位. 因此虽然有点可惜, 但也不得不浪费.
假设我们要在第一页第一行第三列写下1, 别忘记我们已经在上面占用了第二列, 因此, 位置就是:

1-1-3-1: 0000 0001 0000 0000

这是完全可以避免的浪费! 因为我们只需要 8 bits(1 Byte)就完全够了.

现在能理解为什么早期要将数据类型分为如此多的种类吗? 为了节约内存.
以下展示 C 的部分数据类型:
| 类型| 数位长 | 十进制范围 |
| :-: | :-: | :-:|
|short int|2B| -32,768 ~ 32767|
|unsigned short|2B|0 ~ 65536|
|int|4B|-2147483648 ~ 2147483647|

聪明如你一定注意到了, 同样是 2B, 为什么 short int 表达的范围比 unsigned short 小呢? 这是因为可以用一个数位表达这个数的正负. 而 int 就是简单粗暴的合并了更多的存储单元了.

数据类型: 现代编程语言

节省 RAM 是一件好事, 即使是现在, 运算最快最快的编程语言肯定是对 RAM 斤斤计较的语言. 但是你一定想不到 C 居然有十几种”数字”类型. 想象一下, 你每次编程都要在十几种”数字”类型中挑选一个? 因此, 现在编程语言强化了与人之间的交互, 也就是适当的牺牲运行速度, 提高你的编程速度. 比如 Python 的 string 类型. Python 和现代编程语言一样, 它们大多数现在只用 string 这一种”字符”类型, 中文称作字符串. 而”数字”类型也多被简化成了 number 这一种(有些编程语言称作 numeric). 这部分原因是计算机性能大幅提升, 没有了节约的必要(但是大型游戏, 或者极其消耗计算资源的程序一定还是用”原始”的编程语言, 因为更快). 还有可能是现代编程语言能够更智能的合并数据单元.

到这里就结束了, 留一个小问题, C, C++ 各有多少种”字符”类型?