1、正文部分
1
话题引出
技术交流群一个小哥贴出了如下图片 :
问到了共联体类型强制转化的问题,当时bug菌点开看到这几行代码便产生了莫名的亲切感,或许这些就是C语言的魅力所在吧。
其实这种操作在通信协议中拆包、解包是非常常见的,但是笔者也是在参加工作以后在部门的代码中get到,所以这里整理分享给各位。
2
操作解析
有认真阅读过笔者公众号文章的小伙伴,应该在其他文章中也看到过这种操作,不过比较分散,今天抽出来再好好聊聊!
1
buff直接转结构体
上图是简单的协议包,包括帧头,长度和数据部分,在通信数据接收或者发送末端其都位于字节流中,比如UART通信,最后都是放到Sendbuff[N]或者RecBuff[N],然后发送出去。
如果你打包好了结构体,然后一个个填充byte到发送或者接受buff,着实有点麻烦,然而通过结构体指针强制类型转换为uint8_t *pSendBuff;然后在进行字节流发送,那就简洁很多了。
当然在此过程中你还要注意字节序、对齐等等,在往期的文章中bug菌都有讲到,模拟此过程参考下面代码。
参考示例:
#include#include #pragma pack(1) typedef struct _tag_Pack { int Head; int Len; char Data[2]; } sPack; int main(int argc, char *argv[]) { sPack stSendPack; sPack *pstRevPack = NULL; unsigned char *SendBuff =NULL; unsigned char RevBuff[20] ={0}; int cnt = 0; //模拟封包 stSendPack.Head = 0xFF; stSendPack.Len = 0x08; stSendPack.Data[0] = 0x1; stSendPack.Data[1] = 0x2; //模拟发送包 SendBuff = (unsigned char *)(&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 "); return 0; }
运行结果:
2
buff直接转结构共联体
上一节我们谈到了接受和发送的buff直接转结构体,然后进行解包处理,而交流群里面图片中是转共联体,可以说这样的数据结构结合是非常完美的。
buff转结构体类型,就必须buff字节流里的格式与结构体一致,才能正确的解析,而共联体是一种复合类型结构,可以存在多种形式的数据提取,这样就可以带来更多的灵活度,下面代码在操作一波。
参考示例:
#include#include #pragma pack(1) typedef struct _tag_PackType1 { int Head; int Len; char Data[2]; } sPackType1; typedef struct _tag_PackType2 { int Head; int Len; int Data[2]; } sPackType2; typedef struct _tag_PackType3 { int Head; int Len; float Data[2]; } sPackType3; //结构共联体 typedef union _tag_PackType { sPackType1 stPackType1; sPackType2 stPackType2; sPackType3 stPackType3; } uPackType; //不同结构体类型的解析函数 void ParsePackType1(uPackType *punPackType) { punPackType->stPackType1.Head = 0xF1; //you do something! } void ParsePackType2(uPackType *punPackType) { punPackType->stPackType2.Head = 0xF2; //you do something! } void ParsePackType3(uPackType *punPackType) { punPackType->stPackType3.Head = 0xF3; //you do something! } /****************************************** * Fuction: Buff转结构共联体 * Author :(公众号:最后一个bug) *****************************************/ int main(int argc, char *argv[]) { uPackType *punPackType; unsigned char RevBuff[20] ={0}; //通信字节流接受到 RevBuff以后强转 punPackType = (uPackType*)RevBuff; //根据自身需要,不同的解析函数,统一传递共联体即可 ParsePackType1(punPackType); ParsePackType2(punPackType); ParsePackType3(punPackType); printf(" 欢迎关注公众号:最后一个bug "); return 0; }
以上就是今天的全部内容,enjoy!
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !