1、正文部分
1
話題引出
技術(shù)交流群一個小哥貼出了如下圖片 :
?
問到了共聯(lián)體類型強制轉(zhuǎn)化的問題,當時bug菌點開看到這幾行代碼便產(chǎn)生了莫名的親切感,或許這些就是C語言的魅力所在吧。
其實這種操作在通信協(xié)議中拆包、解包是非常常見的,但是筆者也是在參加工作以后在部門的代碼中g(shù)et到,所以這里整理分享給各位。
2
操作解析
有認真閱讀過筆者公眾號文章的小伙伴,應該在其他文章中也看到過這種操作,不過比較分散,今天抽出來再好好聊聊!
1
buff直接轉(zhuǎn)結(jié)構(gòu)體
上圖是簡單的協(xié)議包,包括幀頭,長度和數(shù)據(jù)部分,在通信數(shù)據(jù)接收或者發(fā)送末端其都位于字節(jié)流中,比如UART通信,最后都是放到Sendbuff[N]或者RecBuff[N],然后發(fā)送出去。
如果你打包好了結(jié)構(gòu)體,然后一個個填充byte到發(fā)送或者接受buff,著實有點麻煩,然而通過結(jié)構(gòu)體指針強制類型轉(zhuǎn)換為uint8_t *pSendBuff;然后在進行字節(jié)流發(fā)送,那就簡潔很多了。
當然在此過程中你還要注意字節(jié)序、對齊等等,在往期的文章中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; //模擬發(fā)送包 SendBuff=(unsignedchar*)(&stSendPack); printf("SendData:"); for(cnt=0;cntHead); 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(" 歡迎關(guān)注公眾號:最后一個bug "); return0; }
運行結(jié)果:
2
buff直接轉(zhuǎn)結(jié)構(gòu)共聯(lián)體
上一節(jié)我們談到了接受和發(fā)送的buff直接轉(zhuǎn)結(jié)構(gòu)體,然后進行解包處理,而交流群里面圖片中是轉(zhuǎn)共聯(lián)體,可以說這樣的數(shù)據(jù)結(jié)構(gòu)結(jié)合是非常完美的。
buff轉(zhuǎn)結(jié)構(gòu)體類型,就必須buff字節(jié)流里的格式與結(jié)構(gòu)體一致,才能正確的解析,而共聯(lián)體是一種復合類型結(jié)構(gòu),可以存在多種形式的數(shù)據(jù)提取,這樣就可以帶來更多的靈活度,下面代碼在操作一波。
參考示例:
#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; //結(jié)構(gòu)共聯(lián)體 typedefunion_tag_PackType { sPackType1stPackType1; sPackType2stPackType2; sPackType3stPackType3; }uPackType; //不同結(jié)構(gòu)體類型的解析函數(shù) 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轉(zhuǎn)結(jié)構(gòu)共聯(lián)體 *Author:(公眾號:最后一個bug) *****************************************/ intmain(intargc,char*argv[]){ uPackType*punPackType; unsignedcharRevBuff[20]={0}; //通信字節(jié)流接受到RevBuff以后強轉(zhuǎn) punPackType=(uPackType*)RevBuff; //根據(jù)自身需要,不同的解析函數(shù),統(tǒng)一傳遞共聯(lián)體即可 ParsePackType1(punPackType); ParsePackType2(punPackType); ParsePackType3(punPackType); printf(" 歡迎關(guān)注公眾號:最后一個bug "); return0; }
以上就是今天的全部內(nèi)容,enjoy!
審核編輯:劉清
-
C語言
+關(guān)注
關(guān)注
180文章
7614瀏覽量
137412 -
uart通信
+關(guān)注
關(guān)注
0文章
19瀏覽量
7012
原文標題:結(jié)構(gòu)體嵌入共聯(lián)體在協(xié)議解析中的技術(shù)性操作~
文章出處:【微信號:嵌入式情報局,微信公眾號:嵌入式情報局】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論