如何正确地将接收到的数据放置到结构(C)?

如何正确地将接收到的数据放置到结构(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字节逗号 数据块(设为粗

问题仅适用于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字节逗号

  • 数据块(设为粗体)

  • “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