前几天给人讲课,讲到了这个数组,然后有了更加深刻的理解。我觉得从物理和数据的组织方式上面入手是好的。
先说物理上面是怎么样的。我们先想想,假如让你设计,你咋搞?
肯定是先设计一些基本的数据单元,就好像一个1CM的小格子一样。这么多的小格子怎么放呢?
可以变成一个长条形,但是延伸到很远也不现实,那我们就在平面上面扩展,也就是表,矩阵这种的感觉。
SO?我们要考虑操作,无非就是读写,但是这是高层的操作。具体一点呢?你要指定对什么位置的数据做处理,我们很自然的使用坐标系来做定位。但是一层也不够,那就再叠起来,叠的多了就好像是书本一样,我们称这样的东西叫页。叠的页多了,我们就可以称为块(Bank)
就是上面看见的黑块子
Channel > DIMM > Rank -> Chip -> Bank -> Row/Col
当然了可以看到更加高层管理芯片,DIMM,多个内存条又叫通道。
这个是管理的结构
看一个三星的片子
这个是Bank的黑片子,里面的红色是地址
每个小块的连接
再看一个
所有文章都会抄的图
https://www.mouser.sg/pdfdocs/8GBAS4C512M16D3L.PDF
在这里
前面最重要的就是地址的管理,一个管理行,一个管理列,使用了16bit的位宽来指定地址。
上面的数据是这个内存单体的大小
说了这么多,就是想告诉你,在内存里面,也是行列管理内存单元的。每次操作都是要先知道地址在哪里,然后再这块地址上面做什么操作。
所以也引出来了和这种物理结构最像的数据结构-数组,一段相同变量放在一起,在内存上面是连续的。
它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。
我们也可以使用上面的性质来使用指针操作,数组是一种引用类型数据,存放在内存中。
数组在内存中开辟是线性连续且递增的
指针和数组的纠缠 可以看这个。
C语言编译器要求在编译期间就需要确定数组的内存大小。
在c语言中,任何变量(基本变量,指针变量,结构体变量,数组变量)的空间都是整体开辟,但任何元素的起始地址一定是开辟字节当中最小的。
有两个核心指标,一个是索引,一个是值,前面来定位,后面来存放值。
也可以把它竖起来
数组元素可以通过数组名称加索引进行访问。元素的索引是放在方括号内,跟在数组名称的后边。例如:数组名[元素索引值].
至于初始化,我们要知道,基本的元素类型是什么?有多少。把握这两个,上面的初始化就很简单。不指定就直接数,如果数和个数不对,那就是补全0.
定义格式:元素类型 数组名[m][n]
,可以理解为m行n列的矩阵。
列数n必须给出,行数m可以由编译器数出。
每行一个大括号 {} ,用逗号分隔。也可以没有大括号按序排列。
如果省略则表示补零,也可以用定位初始化。
二维数组在内存里面也是连续的
看这个排列
元素之间是互相连续的,行与行之间是连续的。
初始化就是这样的
数组就是这样,有数组名,然后就是一行对应一列。
第一层是先进去读取二维数组的第一行,其实就是做定位。
第二层是对这一行的每一个元素做处理。做完以后,继续第一层转到下一行。
循环就是为了定位位置,所以说是元素级别的操作。
这个是定位的情况,先看行,再看列
看这个,规模是35
行是5,列是7
我什么写这个?因为在嵌入式系统里面,串口是一个常用的接口,我们除了知道这个物理电气,还要知道真正的数据层是如何定义的。
一般会这样设计,头尾+负载
正好我们可以搞一个数组把里面内容存好,串口的可以使用字节传输,所以这些都可以定义成几个字节的协议帧。
我们可以使用这三种方式来读取数据有没有来,就是在MCU上面执行这个代码。
数据来了,为了平衡这个数据流的速度不匹配,加了缓冲区,其实就是一个没有被使用的数组,装进去慢慢的处理:
我们把数组的数据给处理函数
根据协议解析接收到的数据包,提取命令字和数据内容。
如果我们上位机发送给下位机的时候,也是需要这样编码的
发送简单
上位机也会解读来自下位机的数据帧。
当然了,也会使用更近一步的接收函数
我们也要加入交互!
直接建立连接
发完以后就等着
有一个叫BOSE-055的芯片
看看大厂是这么个做法
先是头,后是操作,地址,长度,数据
具体的例子
所以计算机最中最重要的是-字节!
https://blog.51cto.com/panyujie/3222542