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