计算机基础知识之内存

计算机是进行 「数据处理」 的设备,而程序表示的就是处理顺序和数据结构。由于处理对象(数据)是存储在 「内存」 和 「磁盘」 上的,因此我们今天来聊聊内存和磁盘。
内存的物理机制❝内存实际上是一种名为 「内存ic」 的电子元件。

「内存ic」 中有 「电源」 、 「地址信号」 、 「数据信号」 、 「控制信号」 等用于输入输出的大量 「引脚」 (ic的引脚),通过为其 「指定地址」 ,来进行数据的读写。
下图是 「内存ic」 的引脚配置示例。
vcc和gnd是**「电源」**a0~a9是 「地址信号」 的引脚d0~d7是 「数据信号」 的引脚rd和wr是 「控制信号」 的引脚将电源连接到vcc和gnd后,就可以给其他引脚传递比如0或1这样的信号。大部分情况下,+5v的 「直流电压」 表示1,0v表示0。
「数据信号」 引脚有d0~d7共8个,表示 「一次可以输入输出8位」 (=1字节)的数据。「地址信号」 引脚有a0~a9共10个,表示可以指定0000000000~1111111111共1024个地址由于地址用来表示数据的存储场所,因此我们可以得出这个 「内存ic」 可以存储1024个1字节的数据。又因为1024=1k,所以内存ic的容量就是1kb。
向内存ic读写数据写入数据假设我们往内存ic中写入1字节的数据。
可以给vcc接入+5v,给gnd接入0v的电源并使用a0~a9的 「地址信号」 来指定**「数据的存储场所」**然后把数据的值输入给d0~d7的数据信号并**「把wr(write的缩写)信号设定为1」**执行完这些操作,就可以在 「内存ic」 内部写入数据了。
读取数据在读取数据时,只需要通过a0~a9的地址信号指定数据的存储场所,然后再 「将rd(read的缩写)信号设成1」 即可。执行完这些操作,指定地址中存储的数据就会被输出到d0~d7的数据信号引脚中。
像wr和rd这样可以让ic运行的信号称为 「控制信号」 。
❝ 「内存ic」 内部有大量可以存储8位数据的地方,通过地址指定这些场所,之后即可进行数据的读写。

内存的逻辑模型❝内存的逻辑模型是楼房

上图表示的是,内存为1kb时,有1024层的楼房,每层都有1字节的数据。并且地址的值是从上往下逐渐变大的。
不过,在实际的 「编程环境」 下,还包含着物理内存中不存在的概念,那就是 「数据类型」 。在编程语言中的 「数据类型」 表示存储的是何种类型的数据。从内存来看,就是占用的内存大小(占有的楼层数)的意思。
❝即使是 「物理」 上以1个字节位单位来逐一读取数据的内存,在 「程序」 中,通过指定其类型,也能实现以 「特定字节数」 为单位来进行读写

我们通过一个具体示例来进行说明。
下面是一个往a、b、c这三个变量中写入数据123的c语言程序,
// 定义变量char a;short b;long c;// 给变量赋值a = 123;b = 123;c = 123;这3个变量表示的是内存的特定区域。
❝通过使用变量,即便不指定 「物理地址」 ,也可以在程序中对内存进行读写。

这是因为,在程序运行时候,操作系统会 「自动决定」 变量的物理地址。
在3个变量的数据类型分别是
char:1字节长度short:2字节长度long:4字节长度因此,虽然同样是数据123,存储时其占据的内存大小是不一样的。
上面的示例图中,采用的是 「将数据低位存储在内存低位地址」 的低字节序little endian方式。
由此,我们可以得出一个结论: 「根据程序中所指定的变量的数据类型的不同,读写的物理内存大小也会随之发生变化」 。
数组是高效使用内存的基础❝ 「数组」 是指多个 「同样数据类型」 的数据在内存中连续排列的形式。

作为数组元素的各个数据会通过 「连续的编号」 被区分开来,这个编号称为 「索引」 。 「指定索引后,就可以对该索引对应地址的内存进行读写操作」 。
如下用c语言定义char类型、short类型、long类型三个数组。
char g[100];short h[100];long i[100];数组的定义中所指定的数据类型,表示一次能够读取的内存大小。
❝数组是使用内存的基本,因为其他的内存使用技能,每一种都需要以数组为基础

栈、队列以及环形缓冲区❝栈和队列,都可以不通过指定地址和索引来对数组的元素进行读写。

栈和队列的区别在于 「数据出入的顺序是不同的」 。在对内存数据进行读写时, 「栈」 用的lifo(last input first out, 「后入先出」 )方式,而 「队列」 用的是fifo(first input first out, 「先进先出」 )方式。
❝在内存中 「预留」 出栈和队列所需要的空间,并确定好写入和读出的顺序,就不用再指定地址和索引了

我们假定往栈中写入数据的函数名为push,把栈中读出数据的函数名为pop
使用栈// 往栈中写入数据push(123); // 写入123push(456); // 写入456push(789); // 写入789// 从栈中读出数据j = pop(); // 读出789k = pop(); // 读出456l = pop(); // 读出123
❝当我们需要 「暂时」 舍弃当前的数据,随后再 「恢复」 原貌时候,优先选用栈

使用队列假定往队列中写入数据的函数名为enqueue,把栈中读出数据的函数名为dequeue
// 往栈中写入数据enqueue(123); // 写入123enqueue(456); // 写入456enqueue(789); // 写入789// 从栈中读出数据m = dequeue(); // 读出123n = dequeue(); // 读出456o = dequeue(); // 读出789
❝当我们需要处理 「通讯」 中发送的数据时,或由 「同时运行的多个程序」 所发送过来的数据时,会用到这种队列中存储的不规则数据进行处理的方法

队列一般是以环形缓冲区ring buffer的方式来实现的。
假设我们要有6个元素的数组来实现一个队列。这时可以从数组的 「起始位置」 开始有序地存储数据,然后再按照存储时的顺序数据读出。在数组的末尾写入数据后,后一个数据就会被写入数据的起始位置(此时数据已经被读出所以该位置是空的)
环形缓冲区的模型
链表❝通过使用链表,可以更加高效地对数组数据(元素)进行 「追加」 和 「删除」 处理

在数组的各个元素中, 「除了数据的值之外,通过为其附带上下一个元素的索引」 ,即可实现链表。 「数据的值和下一个元素的索引组合在一起」 ,就构成了数组的一个元素。
由于链表末尾的元素没有 「后续」 的数据,因此就需要用别的值(这里是-1)来填充。
在需要追加或删除数据的情况下,使用链表是很高效的。
这里,我们把之前我们针对js链表相关算法的一些技巧直接迁移过来了。这里使用 「哨兵节点」 来对链表操作进行简化处理。
❝ 「哨兵节点」 是为了简化处理链表 「边界条件」 而引入的**「附加链表节点」**

哨兵节点通常位于 「链表的头部」 ,它的值没有任何意义。在一个有哨兵节点的链表中, 「从第二个节点开始才真正的保存有意义的信息」 。
追加数据function append(head,value) { // 哨兵节点 let dumy = new listnode(0); dumy.next = head; // 遍历链表,直到链表尾部 let node = dumy; while(node.next!=null){ node = node.next; } node.next = new listnode(value); return dumy.next;}首先,创建一个 「哨兵节点」 (该节点的 「值」 没有意义 -即listnode(0)参数为啥不重要),并把该节点当做链表的头节点, 「把原始的链表添加到哨兵节点的后面」 (dumy.next = head)。
然后,返回真正的头节点(哨兵节点的下一个节点)node.next
这里有一个小的注意点,就是在 「遍历」 链表的时候,并不是直接对dumy进行处理,而是用了一个 「零时游标节点」 (node)。这样做的好处就是,在append操作完成以后,还可以通过dumy节点来,直接返回链表的头节点dumy.next。因为,dumy一直没参与遍历过程。
删除数据❝为了删除一个节点,需要找到被删除节点的 「前一个节点」 ,然后把该节点的next指针指向它 「下一个节点的下一个节点」 。

「哨兵节点」 ,在删除指定节点
function delete(head ,value){ let dumy = new listnode(0); dumy.next = head; let node = dumy; while(node.next!=null){ if(node.next.value==value){ node.next = node.next.next; barek; } node = node.next; } return dumy.next;}通过哨兵节点(dumy)直接将 「链表为空」 和 「被删除节点是头节点」 的两种特殊情况,直接囊括了。用最少的代码,处理最多的情况
二叉树「二叉树查找树」 是指在链表的基础上往数组中追加元素时,考虑到数据的大小关系,将其分成左右两个方向的表现形式。
❝二叉查找树使 「数据搜索」 更有效。

❝「我们这里不对具体的数据结构进行详细的介绍。如果了解更多关于数据结构的和对应的算法的东西,可以移步到我们之前的文章中。」 总有一款适合你。

人工智能(AI)芯片产业生态梳理
自由高度板对板连接器:领先数据传输速度达32 Gbps及以上
浅谈SoC时代芯片设计与封装和PCB
FossilEXPLORIST探险家系列第四代智能触屏腕表评测 到底怎么样
环保用电无线计量仪表对接昊美平台的实例说明
计算机基础知识之内存
国内新能源车市场继续壮大 将面临众多挑战
拿森联手北汽新能源 将在线控底盘技术产品上展开深度合作
新能源汽车研发企业的真实反馈:为何选择FLIR自动化热像仪
浅谈科大讯飞用人工智能建设美好世界的展示
2014 TI杯全国大学生物联网设计竞赛在上海交通大学举行
探寻中国工业物联网的破局之路
华为多屏协同功能到底有多实用
你知道直线导轨的品牌吗?
面向系统的板级电源管理方法:CompactPCI电路板的电源
SpaceX星链将支持手机直连 初始网络速度仅能电话短信
轻薄不是唯一?国产笔记本直面MacBook Pro
高速DAC控制功率放大器斜坡曲线
UV光固化有机硅硅胶胶水的简单介绍
B-L4S5I-IOT01A实现安全启动和安全固件安装方案