【单片机】什么年代了还在用传统方法移位解析数据包

发布时间 2023-07-11 16:03:12作者: 不才狸子

通过指针操作来从缓冲区中直接提取值

最近期末在做“医疗器械综合课程设计”,我比舍友提前做完了(其实是我小组ddl早两天)……热心的我就来帮舍友的项目指指点点。他们用到一个手机来和蓝牙模块通信,但是在单片机上解析数据包的时候遇到了困难,网上的例程他们想添加数据包内容不会改了。

假设数据包结构:

以下是他们的源码,从蓝牙模块送的例程修改来的:

一看到这代码我就蒙了,从哪循环到哪?移了多少位?为什么要*8?将来怎么扩展数据包?‍????

数据包缓存就在内存中的某处,要是可以指挥CPU从内存中数据缓冲区中间的一个地址开始读4个字节,然后赋值给另一个变量就好了。凭借着我对C语言指针的认识和对计算机基础的理解,我顿悟了:

char a[] = {0x52, 0xbf, 0x01, 0x00};  // 114514
int b = *(int*)&a[0];
printf("%d\n", b);


结果如同预计的,假设a是缓冲区,从“0”开始读了int(4byte)长度的数据赋值给b。

原理分析

堆栈

堆栈从高地址往低增长。那么这个数据在内存里大概是像这样:

需要注意对char类型指针++是+1,而对int类型指针++是+4。

命令解析

&a[0]

数组a长度为4,&a[0]为数组a第一个char的地址。

(int*)

C语言的类型强制转换。把char类型的指针转换为int类型的指针,这就是精华操做,否则*&a[0]就是a[0]本身。

*

提领,也叫解引用,即dereference,返回内存地址中对应的数值。我见到这个词是在《Essential C++》,特别形象。“解引用”解什么?引用怎么解?而“提领”这个词就让人感觉是给我一个名字常威(地址),从牢里(内存)把常威本人(数值)给提领出来。

*(int*)&a[0]:把a[0]的地址强制转换成指向int类型(4byte)的指针并提领值。


以上的方法可能我在教科书里学过又忘了,而我又凭借着自己的理解顿悟出来。沾沾自喜没几天,我问ChatGPT遇到这种情况怎么办,他是这样做的:

显然这是通用的做法,而且他还给出了详细的文字解释,显得我很呆?