如何正确地将接收到的数据放置到结构(C)?
问题仅适用于C。向量、列表和C++ <强>不< /强>求解。< /P> 我有接收数据的缓冲区: (从那里和更远的U8是uin8_t(无符号字符),依此类推) 数据被打包(它总是有关于开始、结束和len的信息) 数据示例(十六进制): (1包) 240c00020011AA0d78 C8 (2包) 240F 0002 00 00 14D0 07 000D 7D 53 在这里:如何正确地将接收到的数据放置到结构(C)?,c,struct,C,Struct,问题仅适用于C。向量、列表和C++ 不< /强>求解。< /P> 我有接收数据的缓冲区: (从那里和更远的U8是uin8_t(无符号字符),依此类推) 数据被打包(它总是有关于开始、结束和len的信息) 数据示例(十六进制): (1包) 240c00020011AA0d78 C8 (2包) 240F 0002 00 00 14D0 07 000D 7D 53 在这里: “24”-数据包的开始 2字节的完整数据包长度(bold) 4字节-特殊ID(这里是02 00) 1字节逗号 数据块(设为粗
- “24”-数据包的开始
- 2字节的完整数据包长度(bold)
- 4字节-特殊ID(这里是02 00)
- 1字节逗号
- 数据块(设为粗体)
- “0D”-数据包的结尾
- 最后2个字节-CRC
typedef __packed struct FM_Packet_s
{
U8 head;
U16 len;
U32 uid;
U8 cmd;
U8 data;
U8 end;
U16 crc;
} FM_Packet_t, *FM_Packet_p;
U8 RX_buff[255];
…
FM_Packet_t *pFM_Packet = (FM_Packet_t *) &RX_buf;
handlerData()
{
// check received CRC
if(pFM_Packet->uid == ID_NUMBER)
{
if(pFM_Packet->cmd == NEEDED_COMMAND)
{
// command received, make actions
if (pFM_Packet->data == SPECIAL_DATA)
{
// do stuff
}
}
}
}
一切都很好,直到我收到第二个数据包,其中有超过1字节的数据字段
当然,字段“数据”可能有不同的长度,不仅仅如这两个数据包所示
如何处理(正确放置到结构中)接收到的数据
U8 data;
需要是指向缓冲区的指针,该缓冲区的大小适合保存数据,而不是无符号整数
在加载数据之前,需要将缓冲区分配为所需的大小,然后将指针指向它
您还可以将数据包缓冲区扩大很多,并使用U16 len
以确定数据停止的位置
需要是指向缓冲区的指针,该缓冲区的大小适合保存数据,而不是无符号整数
在加载数据之前,需要将缓冲区分配为所需的大小,然后将指针指向它
您还可以将数据包缓冲区扩大很多,并使用U16 len代码>以找出数据停止的位置。您可以使用“C的不必要的友好性”
它使用了一个灵活的数组,[1]只是为了让编译器保持安静。在挑剔的编译器上,您可能会收到关于数组大小的警告。如果我们将pFM_数据包->len分配给len
- 阵列的大小为len-11
- 最后是at&pFM_数据包->数据[len-11]
- CRC是at&pFM_数据包->数据[len-10]
如果您使用的是gcc,那么可以使用允许声明
U8 data[0];
这在大多数编译器中是非法的,但gcc允许这样做。您可以使用“C的不正当友好性”
它使用了一个灵活的数组,[1]只是为了让编译器保持安静。在挑剔的编译器上,您可能会收到关于数组大小的警告。如果我们将pFM_数据包->len分配给len
- 阵列的大小为len-11
- 最后是at&pFM_数据包->数据[len-11]
- CRC是at&pFM_数据包->数据[len-10]
如果您使用的是gcc,那么可以使用允许声明
U8 data[0];
<>这在大多数编译器中是非法的,但是GCC允许它。我不认为C支持结构中间的可变长度数组。我想你只需要直接引用后面的字节,或者为它们定义一个包尾结构,或者别的什么。不要依赖于编译器的结构安排。始终逐段读取数据并将其存储在结构中。当且仅当结构通过同一可执行文件加载回时,读取和写入原始数据结构才有效。如果是新版本或不同的编译器设置,该结构可能会转变为不兼容的形式。@tadman我认为这就是\uu packed
的目的。@Rup我只相信这一点,编译器不会像错误对齐值一样,而且这里还有endian问题要处理。\uuuu packed
是对编译器的请求,还是一个硬需求?使用跨编译域的结构是不可靠的,您应该避免这种方法。看看你的数据包结构,没有理由去麻烦一个结构,只是增加了风险和长期维护代码,否则将不需要任何。我不认为C支持一个可变长度的数组在一个结构的中间。我想你只需要直接引用后面的字节,或者为它们定义一个包尾结构,或者别的什么。不要依赖于编译器的结构安排。始终逐段读取数据并将其存储在结构中。当且仅当结构通过同一可执行文件加载回时,读取和写入原始数据结构才有效。如果是新版本或不同的编译器设置,该结构可能会转变为不兼容的形式。@tadman我认为这就是\uu packed
的目的。@Rup我只相信这一点,编译器不会像错误对齐值一样,而且这里还有endian问题要处理。\uuuu packed
是对编译器的请求,还是一个硬需求?使用跨编译域的结构是不可靠的,您应该避免这种方法。查看您的数据包结构,没有理由为结构而烦恼,只需为原本不需要的代码添加风险和长期维护。“其中是否有一个字段告诉您数据负载有多大?您需要一个”-不,但我始终知道数据的完整长度。数据包的其他部分总是有相同的大小,所以我想我可以计算有效载荷。我刚找到。我想这个结构是有线格式的,不是吗?因此,不是分配一个可变长度缓冲区来存储数据,而是在一个缓冲器中处理数据,我们已经在中间有一个可变长度的块。@ RUP缓冲区当前是固定长度的,OP将可变长度的数据放在其中。要么缓冲区需要增长,要么内存需要分配给可变长度部分。@Rup您可能是对的。我找不到FM_数据包的定义,但如果它是一个标准,OP pr