我有一个C程序接收一个64字节的char数组(通过USB传递)。根据第一个字节(表示命令类型),我想在char数组上“强加”一个结构,以使代码更清晰。
例如,如果命令代码是10,我会期望类似:
struct
{
uint8_t commandNumber;
uint16_t xPos;
uint16_t yPos;
int32_t identificationNumber;
} commandTen;
所以我想将我的char数据包[64]'投射到'commandTen上,然后使用类似的东西访问字段:
localVar = commandTenPacket->xPos;
如何在C中实现?
提前致谢!
答案 0 :(得分:8)
首先,正如其他人所说,你必须确保你的struct
没有填充。您的编译器可能有一个扩展名,#pragma pack
左右。
为每个用例定义struct
,而不是示例中的变量。
然后定义union
typedef union overlay overlay;
union overlay {
uint8_t raw[64];
struct type10 command10;
struct type42 command42;
};
现在创建一个该类型的缓冲区
overlay buffer;
将“raw”部分提供给接收数据的函数:getit(buffer.raw)
。然后
switch (buffer.raw[0]) {
case 10: {
// use buffer.command10
break;
}
case 42: {
// use buffer.command42
}
}
这可以保证C标准运行良好,因为您正在阅读uint8_t
AKA unsigned char
。实际上,union
s的主要用例就是这种“类型惩罚”。具有不同类型的IPv4,IPv6等地址的整个网络层以类似的方式工作。
答案 1 :(得分:1)
不要施放。使用memcpy
char packet[64];
...
assert(sizeof commandTen <= sizeof packet);
memcpy(&commandTen, packet, sizeof commandTen);
这假设大小和内存布局匹配正确(基于强制转换的解决方案将使用相同的假设)。
答案 2 :(得分:0)
有一种方法可以使用指针。让我试着用这种方式解释一下:
struct commandX {
int x;
};
struct commandMessage {
char[8] msg;
};
char* message = (char*) malloc(sizeof(char)*9); // this will allow us a struct
// size of 8 bytes, since the
// first byte will store the
// information on how to inter-
// the memory (or you do it in
// a different way).
// 1. determine your offset
// in this case, it would be the length of the command on how to interpret.
// basically, it has to be the count of bytes from the
// beginning of your message to the start of your struct
int offset = sizeof(char) * 1;
// 2. read the command (that would be: message[0])
// 3. now get rid of the type information, so that you can address every byte
void* temp = (void*) message;
// 4.1 if it is commandX:
struct commandX *x_temp = (struct commandX*) (temp+offset);
// use x_temp->x
// 4.2 if it is commandMessage:
struct commandMessage *msg_temp = (struct commandMessage*) (temp+offset)
// use msg_temp->msg