2016-11-03 82 views
3

我在將消息解析爲結構時遇到了一些麻煩。我知道消息被分解成字節,並且消息總是會有11個字節長。有人告訴我,解析數據的一個非常優雅的解決方案就是將傳入緩衝區轉換爲字節結構。我的問題是如何執行該功能。我聽說通過將緩衝區轉換爲char *,您應該能夠在一行或兩行中執行轉換。將消息解析爲結構

typedef struct tStateMsg { 
    uint8_t reportID; 
    uint8_t ctrlName1; 
    uint8_t State1; 
    uint8_t ctrlName2; 
    uint8_t State2; 
    uint8_t ctrlName3; 
    uint8_t State3; 
    uint8_t ctrlName4; 
    uint8_t State4; 
    uint8_t ctrlName5; 
    uint8_t State5; 
} StateMsg; 

void SetState(uint8 msgBuffer[], uint8 bufferSize) //BufferSize is always 11 
{ 
    //Parse the message to the struct. 
} 

我知道有更多的錯誤檢查需要確保該消息始終是11個字節長,所有我所期望的數據是存在的,但我會忽略,只是暫時。

謝謝你的幫助!

+0

如果在這裏有填充,但要注意編譯器允許在類成員之間添加填充,我會感到驚訝。這意味着'sizeof(tStateMsg)> = 11' – NathanOliver

+1

C或C++?他們不是同一種語言。我很確定dbush的答案在C++中是非法的。標記其中一個。不是都。 – Asu

+2

你會想看看[Eric Raymond關於結構包裝](http://www.catb.org/esr/structure-packing/)。 –

回答

3

這是由鑄造緩衝區(緩衝區開始實際的地址)的指針結構完成:

StateMsg *msg = (StateMsg *)msgBuffer; 

然後,你可以參考struct成員。

你需要注意的一件事是對齊。如果緩衝區由malloc創建,則該緩衝區將針對任何數據類型正確對齊。但是,如果緩衝區是本地陣列,則可能不會在適合於StateMsg的邊界上進行分配。

所以一定要使用malloc'ed緩衝區,以解決對齊問題。

對於struct元素之間的填充,編譯器可以自由地在所認爲合適的地方插入填充。爲了確保結構符合您的期望,您希望聲明您的struct已打包。在gcc中,你可以用#pragma packed來做到這一點。然而,在實踐中,只要你將每個元素放在適當的偏移處(例如,2字節偏移處的2字節類型,4字節偏移處的4字節類型),你最終應該得到一個佈局結構:你的期望。在你的具體例子中,你所有的字段都是1個字節,所以除了最後不應該有任何填充。

有關更多詳細信息,請參閱this excellent article on struct packing(感謝Rob K在評論中提出此建議)。

+5

請注意,編譯器允許在成員之間插入填充字節,例如對齊。爲了實施您的解決方案,必須打包結構。許多編譯器都有* pragmas *或選項來將結構聲明爲packed。 –

+1

實際上,對於這個結構,因爲它全部是uint8_t,所以32位代碼的編譯器只會在結構的末尾添加1個字節,以使其達到32位對齊,從而使結構的大小爲3個32位字OR如果以64位代碼爲目標,則會在結構的末端添加5個字節的填充字符以使其達到64位對齊,從而使該結構具有2個64位字的大小(參見http://www.catb.org/)。 ESR /結構包裝/#_ alignment_requirements)。 –