🔥「面试题」数组访问、指针与内存寻址原理

·  阅读 1531
🔥「面试题」数组访问、指针与内存寻址原理

欢迎大家来到"面试"系列,Blue在这个系列中将带领大家探究热门面试题背后的知识和原理,欢迎大家关注我,精彩内容不错过,如果碰到感兴趣的题目想讨论,欢迎大家通过留言告诉我,谢谢,但请记住:

面试或许可以应付,但不要糊弄自己,彻底掌握知识本身才是提升的关键 —— 我说的

内存是所有计算设备的基础,同时也是程序存储数据的重要场所,我们每天都要接触,但是内存或者说随机存储(Random Access Memory-RAM)到底是怎么工作的,我们的程序究竟如何使用内存?这次Blue就带大家一起来研究一下,欢迎点赞、收藏、评论、转发

内容大纲

  • 内存的原理,如何存放数据
  • 内存如何进行寻址、门电路如何组成内存、内存位宽与容量的关系
  • 地址是什么?指针是什么?
  • 数组不同位置的访问速度一样吗?

从面试题开始

有一道很简单的面试题,从它开始今天的话题

数组里面有10万个数据,取第一个元素和第10万个元素的时间相差多少
复制代码

答案显而易见,因为数组中无论访问第几个元素,时间是一样的,所以答案是:一样的

问题是解决了,但数组在内存中究竟是如何存放的?数组究竟是什么?

RAM内存的原理

我们平常说的"内存"其实应该叫"Random Access Memory",即"随机访问存储",它的名字其实已经说明一切了,你可以随机的访问任意一个位置,速度是一样的,但是,为什么?

想象中的内存?

在想象内存时,很多人脑子里会蹦出这幅图:

1

其实上面的图错的最离谱,因为内存是一个一个小格子的感觉没错,但它不是二维的,硬要说的话,更接近一维的数组,长这样其实还准确一些

2

上面这张图如果只是说明内存的一些特性其实倒也够了,不过既然今天咱们打算彻底弄明白内存的访问原理,那么,来看看这个

内存的原理?

其实最接近实际情况的内存示意图,大概长得跟棵树似的,在内存中,存在很多"门"(不是俗称,还真就叫门),假如我们的内存只有2字节,那么它长这样:

3

这里有两个控制位

  • a(address的简称)代表要访问哪个字节,0代表0号字节,1代表1号字节
  • w代表写入标志,0是读取,1是写入(当然,还涉及到寄存器操作,这里省略了)

我们的内存当然不只2字节,那么稍微扩展一下,4字节内存长这样

4

因为有4字节,所以一个a就不够了,这时我们需要2位,a0和a1

这也顺便带给我们2个有意思的现象

  • 内存的容量一定是2的n次方(寻址位数),比如1024(1K)、2048、……、1048576(1M)、……、1073741824(1G)、2147483648(2G)等,你无法让内存的容量是其他值
  • 内存寻址能力(也就是存储上限)受限于主板和操作系统位宽,比如32位系统最大内存寻址上限为4294967296,也就是4GB,这就是为啥32位的Windows XP系统无法使用超过4G内存的根本原因

真实的内存寻址过程

劝退警告,你可以完全忽略此节继续查看其它内容,如果对自己的头发有信心,那么让我们开始吧😂

目前人类的计算机使用了一种称为门的逻辑元件(其实就是三极管堆出来的啦),它能帮我们触发指定的操作,而这里,对我们最重要的是"与"(AND)和"非"(NOT)这两种门,先看个门,呸,看个图(图片引自nutsvolts)

5

这个图简单到一眼就能看懂,那个黑点是输入/输出,圆圈是非操作(NOT),不过为了便于理解,我们来个例子试试

假设我的输入是A=0,B=1,那么A会经过非操作(NOT)变成1,也就是说,最后做的是1&1操作,结果是1

6

好的,门搞明白了(吗?),接下来继续搞内存,它到底怎么寻址的?很简单

7

我们只需要多来几个门,看上图我们可以知道,第0字节在A=00时触发,也就是说,地址0触发了第0字节的操作;第1字节在A=01是触发,也就是说,地址1触发了第1字节的操作,是不是很简单?

顺便一说,门上的输入数量(A的数量)就是寻址宽度,一般俗称位宽,也就是我们内存的容量上限

这跟问题有什么关系?

说了这么多,其实就是为了告诉大家,你访问哪个位置,仅仅跟你Address的值有关,而设置Address其实需要的时间是相同的,比如赋值操作,a=12a=9999其实时间一样,那么,这跟数组有什么关系?

数组在内存中如何存储

数组在内存中占用一段连续的空间(废话,不连续的那叫链表谢谢),而我们在变量中其实就会保存数组的首地址(也就是所占内存的起点),这个地址的值(比如这里的87)被称为指针

8

那么,我们想要arr[1]是如何操作的?很简单:arr[0]是87号位置,那arr[1]呢?小学生,不对,幼儿园都能算出来是88对吧

9

再试一个,arr[99]呢?这个有点难,得小学生才会了,87+99=...,186对吧?

那么问题来了,访问A=87和A=186的时间一样吗?上面就说过,都是给Address赋值,一样的

所以我们的结论是,访问数组的任何一位,时间完全相同

结论

是时候梳理一遍Blue讲过的东西了,那么首先

footer

我们来总结一下,这次说到的内容:

  • 内存通过地址(Address)访问,不同的地址访问时间完全相同
  • 进而,数组不论哪一位,访问时间都是相同的
  • 指针就是存在变量里的内存地址(Address)
  • 内存寻址宽度(位宽)限制了它的容量上限

有bug?想补充?

感谢大家观看这篇教程,有任何问题或想和我交流,请直接留言,发现文章有任何不妥之处,也请指出,提前感谢

分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改