1、正文部分
1
话题引出
技术交流群一个小哥贴出了如下图片 :
问到了共联体类型强制转化的问题,当时bug菌点开看到这几行代码便产生了莫名的亲切感,或许这些就是C语言的魅力所在吧。
其实这种操作在通信协议中拆包、解包是非常常见的,但是笔者也是在参加工作以后在部门的代码中get到,所以这里整理分享给各位。
2
操作解析
有认真阅读过笔者公众号文章的小伙伴,应该在其他文章中也看到过这种操作,不过比较分散,今天抽出来再好好聊聊!
1
buff直接转结构体
上图是简单的协议包,包括帧头,长度和数据部分,在通信数据接收或者发送末端其都位于字节流中,比如UART通信,最后都是放到Sendbuff[N]或者RecBuff[N],然后发送出去。
如果你打包好了结构体,然后一个个填充byte到发送或者接受buff,着实有点麻烦,然而通过结构体指针强制类型转换为uint8_t *pSendBuff;然后在进行字节流发送,那就简洁很多了。
当然在此过程中你还要注意字节序、对齐等等,在往期的文章中bug菌都有讲到,模拟此过程参考下面代码。
参考示例:
#include#include #pragmapack(1) typedefstruct_tag_Pack { intHead; intLen; charData[2]; }sPack; intmain(intargc,char*argv[]){ sPackstSendPack; sPack*pstRevPack=NULL; unsignedchar*SendBuff=NULL; unsignedcharRevBuff[20]={0}; intcnt=0; //模拟封包 stSendPack.Head=0xFF; stSendPack.Len=0x08; stSendPack.Data[0]=0x1; stSendPack.Data[1]=0x2; //模拟发送包 SendBuff=(unsignedchar*)(&stSendPack); printf("SendData:"); for(cnt=0;cnt< sizeof(sPack);cnt++) { printf("0x%02X ",*(SendBuff + cnt)) ; RevBuff[cnt] = *(SendBuff + cnt); //这里模拟接受到数据 } printf(" "); //模拟解包 pstRevPack = (sPack *)RevBuff; printf("pstRevPack.Head = 0x%X ",pstRevPack->Head); printf("pstRevPack.Len=0x%X ",pstRevPack->Len); printf("pstRevPack.Data[0]=0x%X ",pstRevPack->Data[0]); printf("pstRevPack.Data[1]=0x%X ",pstRevPack->Data[1]); printf(" 欢迎关注公众号:最后一个bug "); return0; }
运行结果:
2
buff直接转结构共联体
上一节我们谈到了接受和发送的buff直接转结构体,然后进行解包处理,而交流群里面图片中是转共联体,可以说这样的数据结构结合是非常完美的。
buff转结构体类型,就必须buff字节流里的格式与结构体一致,才能正确的解析,而共联体是一种复合类型结构,可以存在多种形式的数据提取,这样就可以带来更多的灵活度,下面代码在操作一波。
参考示例:
#include#include #pragmapack(1) typedefstruct_tag_PackType1 { intHead; intLen; charData[2]; }sPackType1; typedefstruct_tag_PackType2 { intHead; intLen; intData[2]; }sPackType2; typedefstruct_tag_PackType3 { intHead; intLen; floatData[2]; }sPackType3; //结构共联体 typedefunion_tag_PackType { sPackType1stPackType1; sPackType2stPackType2; sPackType3stPackType3; }uPackType; //不同结构体类型的解析函数 voidParsePackType1(uPackType*punPackType) { punPackType->stPackType1.Head=0xF1; //you do something! } voidParsePackType2(uPackType*punPackType) { punPackType->stPackType2.Head=0xF2; //you do something! } voidParsePackType3(uPackType*punPackType) { punPackType->stPackType3.Head=0xF3; //you do something! } /****************************************** *Fuction:Buff转结构共联体 *Author:(公众号:最后一个bug) *****************************************/ intmain(intargc,char*argv[]){ uPackType*punPackType; unsignedcharRevBuff[20]={0}; //通信字节流接受到RevBuff以后强转 punPackType=(uPackType*)RevBuff; //根据自身需要,不同的解析函数,统一传递共联体即可 ParsePackType1(punPackType); ParsePackType2(punPackType); ParsePackType3(punPackType); printf(" 欢迎关注公众号:最后一个bug "); return0; }
以上就是今天的全部内容,enjoy!
审核编辑:刘清
-
C语言
+关注
关注
180文章
7598浏览量
136169 -
uart通信
+关注
关注
0文章
19浏览量
6999
原文标题:结构体嵌入共联体在协议解析中的技术性操作~
文章出处:【微信号:嵌入式情报局,微信公众号:嵌入式情报局】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论