我在将消息解析为结构时遇到了一些麻烦。我知道消息被分成字节,并且消息总是长达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 :(得分:3)
这是通过将缓冲区(实际上是缓冲区的起始地址)转换为指向struct的指针来完成的:
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在评论中提出这一点)。