首页 > 解决方案 > 如何使用动态改变数据大小的结构?

问题描述

仅针对 C 的问题,C++ 和向量不能解决问题。

我有这样的结构:

typedef __packed struct Packet_s
{
  U8  head;
  U16 len;
  U32 id;
  U8  data;
  U8  end;
  U16 crc;
} Packet_t, *Packet_p;

编辑:U8 是 uint8_t(无符号字符)等等)

例如,我收到了数据包(十六进制):

24 0B 00 07 00 00 00 AA 0D 16 1C

在哪里

头 = 0x24

长度 = 0x0B 0x00

ID = 0x07 0x00 0x00 0x00

数据 = 0xAA

结束 = 0x0D

CRC = 0x16 0x1C

我可以像这样从传入缓冲区中复制它

U8 Buffer[SIZE]; // receives all bytes here
memcpy(&Packet, &Buffer, buffer_len);

并进一步使用它。

如果字段“DATA”长于 1 个字节,是否可以使用我的结构?

我该如何处理这样的事情?

24 0F 00 07 00 00 00 AA BB CC DD EE 0D BD 66

数据包的长度总是已知的(2 和 3 个字节有关于长度的信息)。

编辑:在“句柄”下,我的意思是我接下来要做:

  if (isCRCmatch() )
  {
    if(Packet.id == SPECIAL_ID_1)
    {
      // do something
    }

    if(Packet.id == SPECIAL_ID_2)
    {
      // do other 
    }

    if(Packet.data[0] == 0xAA)
    {
      // do one stuff
    }

    if(Packet.data[1] == 0xBB && Packet.id == SPECIAL_ID_3 )
    {
      // do another stuff
    }

  }

而且(如果可能的话)我想使用相同的结构发送“答案”:

U8 rspData[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};

SendResponce(Packet.id, rspData);

void SendResponce (U8 id_rsp, uint8_t* data_rsp)
{
  Packet_t ResponceData;
  uint16_t crc;
  uint8_t *data;

  ResponceData.head  = 0x24;
  ResponceData.len   = sizeof(ResponceData); // HERE IS PROBLEM ONE
  ResponceData.id   = id_rsp;
  ResponceData.data  = *data_rsp; // HERE IS PROBLEM TWO
  ResponceData.end   = 0x0D; // symbol '\r'

  data = (uint8_t*)&ResponceData;
  crc = GetCrc(data, sizeof(ResponceData)-2); // last 2 bytes with crc

  ResponceData.crc = crc;//(ack_crc >> 8 | ack_crc);

  SendData((U8*)&ResponceData, sizeof(ResponceData));  // Send rsp packet
}

第一个问题 - 我无法自动获取所有结构的大小,因为指针总是 4 个字节......第二个问题 - 我确定我会丢失 rsp 数据,因为我不知道它的结尾在哪里。

标签: cstructurepacketpacket-capture

解决方案


结构中间不能有动态缓冲区。

解决问题的另一种方法是将结构分成两部分。例如(注意data这里是一个灵活的数组成员):

typedef __packed struct Packet_s
{
  U8  head;
  U16 len;
  U32 id;
  U8  data[];
} Packet_t, *Packet_p;

typedef __packed struct PacketEnd_s
{
  U8  end;
  U16 crc;
} PacketEnd_t, *PacketEnd_p;

然后使用

Packet_t *pPacket = (Packet_t *)&Buffer;
PacketEnd_t *pPacketEnd = (PacketEnd_t *)( count pointer here by using pPacket->len );

假设 __packed 允许对 __packed 结构的成员使用未对齐的访问。


推荐阅读