【问题标题】:How properly place received data to structure (C)? [duplicate]如何正确地将接收到的数据放置到结构 (C) 中? [复制]
【发布时间】:2018-09-26 01:30:58
【问题描述】:

问题仅适用于 C。向量、列表和 C++解决。

我有接收数据的缓冲区: (从那里和进一步的 U8 是 uin8_t(无符号字符)等等)

buffer_pic

数据被打包(它总是有关于开始、结束和长度的信息)。

数据示例(十六进制):

(1 包)

24 0C 00 02 00 00 00 11 AA 0D 78 C8

(2包)

24 0F 00 02 00 00 00 14 D0 07 00 00 0D 7D 53

这里:

  • '24' - 数据包开始

  • 2 字节的完整数据包长度(粗体

  • 4字节-特殊ID(这里是02 00 00 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
          }
       }
    }
  }

在我收到第二个数据包之前一切都很好,它在 DATA 字段中有超过 1 个字节。 Now data is blended

当然,“数据”字段可能有不同的长度,不仅仅是这两个数据包中显示的那样。

如何处理(正确放入结构中)接收到的数据?

【问题讨论】:

  • 我认为 C 不支持结构中间的可变长度数组。我想你只需要直接引用后面的字节,或者为它们定义一个 Packet_Tail 结构,或者其他的东西。
  • 不要依赖编译器的结构排列。始终逐段读取数据并将其存储在结构中。当且仅当结构通过相同的可执行文件加载回时,读取和写入原始数据结构才有效。如果是新版本或不同的编译器设置,则该结构可能会转变为不兼容的形式。
  • @tadman 我认为这就是__packed 的用途。
  • @Rup 我只相信这么多,编译器不会像错误对齐的值一样,而且这里还有字节序问题需要处理。 __packed 是对编译器的请求,还是硬性要求?
  • 使用跨编译域的结构我们不可靠,你应该避免这种方法。查看您的数据包结构,没有理由为结构而烦恼,只是为本来不需要任何代码的代码增加了风险和长期维护。

标签: c struct


【解决方案1】:
U8  data; 

需要是一个指向大小合适的缓冲区来保存数据的指针,而不是无符号整数。

在加载数据之前,您需要将缓冲区分配为所需的任何大小,然后将指针指向它。

你也可以让你的数据包缓冲区更大,并使用U16 len;找出数据停止的位置。

【讨论】:

  • “那里是否有一个字段可以告诉您数据有效负载有多大?您需要一个” - 不,但我总是知道完整的数据。数据包的其他部分总是具有相同的大小,所以我想我可以计算有效载荷。
  • 有一个。我刚刚找到了。
  • 我认为这种结构是有线格式,不是吗?因此,这不是分配可变长度缓冲区来存储数据的情况,而是在我们已经拥有的缓冲区中处理数据,中间有一个可变长度块。
  • @Rup 缓冲区当前是固定长度的,OP 正在将可变长度的数据放入其中。要么缓冲区需要增长,要么需要为可变长度部分分配内存。
  • @Rup 你可能是对的。我找不到 FM_Packet_s 的定义,但如果它是标准,则 OP 可能声明不正确。
【解决方案2】:

你可以使用“C 的无根据的 chumminess”http://computer-programming-forum.com/47-c-language/6c323b3186a9a335.htm

typedef __packed struct FM_Packet_s
{
  U8  head;
  U16 len;
  U32 uid;
  U8  cmd;
  U8  data[1];
} FM_Packet_t, *FM_Packet_p;

它使用一个灵活的数组 - [1] 只是为了让编译器保持安静。在挑剔的编译器上,您可能会收到有关数组大小的警告。如果我们将 pFM_Packet->len 分配给 len,

  • 数组的大小是len - 11
  • 结束在 &pFM_Packet->data[len - 11]
  • CRC 位于 &pFM_Packet->data[len - 10]

如果你使用 gcc,你可以使用允许声明的 gcc 扩展

U8 data[0];

这在大多数编译器中是非法的,但 gcc 允许这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-02
    • 2012-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多