将结构添加到C中的char数组中

时间:2012-08-19 06:21:20

标签: c arrays struct

我有一个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中实现?

提前致谢!

3 个答案:

答案 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