c - memcpy to union 没有按预期工作

标签 c struct embedded unions memcpy

我正在开发一些嵌入式软件,并试图让事情变得更加灵活。我希望能够做的其中一件事是更改结构并在整个应用程序的其余部分更改数据处理方式。

我注意到我可以将有效载荷中的一些数据复制到 union 中,但由于某种原因不能复制全部。这是我正在做的:

union ConcentratorPacket {
 struct PacketHeader header;
 struct NetworkJoinReqPacket networkJoinReqPacket;
};

static union ConcentratorPacket latestRxPacket;

地点:

struct PacketHeader {
 uint32_t sourceAddress;
 uint8_t packetType; 
};

struct NetworkJoinReqPacket{
 struct PacketHeader header;
 uint8_t maxDataLen;
};

稍后我想将数据从接收到的数据包移动到这个 union 内的相关结构中,所以我想这样做:

memcpy(&latestRxPacket.networkJoinReqPacket, rxPacket->payload, sizeof(latestRxPacket.networkJoinReqPacket));

其中 rxPacket->payload 是一个 uint8_t 数组,以正确的顺序传送。

我看到的是 packetHeader 使用此方法很好地填充,但 maxDataLen 没有采用正确的值。事实上它取的值是 payload[8] 而不是 payload[5]。

我发现解决这个问题的唯一方法是对 maxDataLen 进行直接赋值,但如果结构因任何原因发生变化,则需要在每个地方进行更改,因此 memcpy 比这个更可取:

 memcpy(&latestRxPacket.networkJoinReqPacket.header, rxPacket->payload, sizeof(latestRxPacket.networkJoinReqPacket.header));
 latestRxPacket.networkJoinReqPacket.maxDataLen = rxPacket->payload[5];

我认为我所看到的表明 memcpy 将 maxDataLen 视为 uint32,右对齐,但我不知道如何避免这种情况。

这很奇怪,因为我在其他地方做了类似的事情并且工作正常,但唯一的区别是与 maxDataLen 等效的是 uint32,而不是 uint8。

如有任何帮助或指导,我们将不胜感激。

最佳答案

正如一些程序员指出的那样,它与结构填充/打包有关。似乎默认情况下,我在 Code Composer Studio 中使用的 TI 编译器填充结构以将它们与 32 位内存对齐。

幸运的是,编译器支持 __attribute__((__packed__))

只需更改 PacketHeader 的定义即可解决问题:

struct __attribute__((__packed__)) PacketHeader {
  uint32_t sourceAddress;
  uint8_t packetType;
};

关于c - memcpy to union 没有按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46238529/

相关文章:

c - 即使在满足条件后,While 循环也不会中断,但如果我在 while 循环中使用 "printf",则相同的代码开始工作

c - Visual Studio - 编译错误

string - 如何将两个字符串字段与另一个字符串连接起来?

C 结构变量访问

c - 如何在linux内核中将一个结构体存储在两个不同的内存页中?

c - 为什么下面的代码会出现段错误?

c - HiTech/Microchip C 的免费静态检查器?

将 float 与零进行比较

C程序只有两个循环

c - 删除链表中的节点