2

我有一个 C 程序,它接收一个 64 字节的 char 数组(通过 USB 传递)。根据第一个字节(指示命令类型),我想在 char 数组上“强加”一个结构以使代码更清晰。

例如,如果命令代码是 10,我会期望类似:

struct
{
    uint8_t commandNumber;
    uint16_t xPos;
    uint16_t yPos;
    int32_t identificationNumber;
 } commandTen;

因此,我想将我的 char packet[64] 'onto' commandTen 转换,然后使用以下内容访问字段:

localVar = commandTenPacket->xPos;

如何在 C 中实现这一点?

提前致谢!

4

3 回答 3

8

首先,正如其他人所说,您必须确保您struct没有填充。你的编译器可能有一个扩展,#pragma pack或者这样。

struct为您的每个用例定义 a ,而不是您的示例中的变量。

然后定义一个union

typedef union overlay overlay;

union overlay {
 uint8_t raw[64];
 struct type10 command10;
 struct type42 command42;
};

现在创建该类型的缓冲区

overlay buffer;

将“原始”部分提供给接收数据的函数:getit(buffer.raw). 进而

switch (buffer.raw[0]) {
 case 10: {
   // use buffer.command10
   break;
 }
 case 42: {
   // use buffer.command42
 }
}

C 标准保证了这一点可以正常工作,因为您将所有内容都阅读为uint8_tAKA unsigned char。事实上,unions 的主要用例就是这种“类型惩罚”。具有不同类型 IPv4、IPv6 等地址的整个网络层以类似的方式工作。

于 2012-08-19T07:40:46.310 回答
1

不要投。采用memcpy

char packet[64];
...

assert(sizeof commandTen <= sizeof packet);
memcpy(&commandTen, packet, sizeof commandTen);

这假设大小和内存布局正确匹配(基于演员的解决方案将使用相同的假设)。

于 2012-08-19T07:43:52.450 回答
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
于 2012-08-19T07:41:03.393 回答