c - 如何使用动态改变数据大小的结构?
问题描述
仅针对 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 数据,因为我不知道它的结尾在哪里。
解决方案
结构中间不能有动态缓冲区。
解决问题的另一种方法是将结构分成两部分。例如(注意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 结构的成员使用未对齐的访问。
推荐阅读
- python - “响应”对象不可调用
- python - 如何在 cplex-python 中设置间隙容差?
- spring - 如何在 Spring AMQP 中使用反应式 RabbitListener 确认/确认?
- java - 在不更改 xml 文件的情况下,无法解析在 java 解析器中具有 html 实体标记属性的 xml
- database - 在哪里将 -ifNotExists 标志添加到 h2 start 命令?
- html - 有没有办法在两个浮动元素之间放置一个 h1 ?
- node.js - 在 Sequelize 中创建关联
- reactjs - 从 npm 模块编辑反应范围滑块中的 CSS
- c# - 如何在另一个 C# 中使用类的变量?
- python - 如何使用条件语句或循环来实现我的要求?