包含结构的 C 联合 - 内存映射 - 编译器跳过一个字节?

C union containing structs - memory mapping - compiler skips one byte?

我知道标题有点混乱。

我创建了一个包含 "raw" 数组和 2 个结构的联合。这 2 个结构各自包含一个结构 header_t、一个结构联合和一个 uint8_t。我只附加了 inMsg_t,因为两个结构的组成方式相同。

typedef struct sAfRegisterSRSP{
    uint8_t Status;
} tAfRegisterSRSP;

typedef union InOutMsg_u{
    uint8_t raw[ZIGBEE_PAYLOAD_MAX];
    outMsg_t outMsg;
    inMsg_t inMsg;
}msg_t;   


typedef struct header_s{
    uint8_t len;    ///< packet len 
    uint8_t cmd0;   ///< type (Bit: 7-5) and subsystem (Bit 4-0))
    uint8_t cmd1;   ///< command identifier
}header_t;


typedef struct inMsg_s{
    header_t header;
    union payload_u{
        tAfRegisterSRSP               afRegisterSRSP;
        tAfDataRequestSRSP            afDataRequestSRSP;
        tAfIncomingMsgAREQ            afIncomingMsgAREQ;
        tAfDataConfirmAREQ            afDataConfirmAREQ;

        tZbStartRequestSRSP           zbStartRequestSRSP;
        tZbPermitJoiningRequestSRSP   zbPermitJoiningRequestSRSP;
    } payload;
    uint8_t checksum;   //just a placeholder; cannot be used practically
}inMsg_t;

现在,当我 运行 代码时 header-bytes 的内存映射很好。原始数组的 byte[0] 映射到 header-struct 中的 len-field。 cmd0 和 cmd1 也是如此。但是,afRegisterSRSP-struct 中的 "status" 并不指向 status-byte,而是指向状态字节之后的 CRC-Byte。当查看内存地址时,这一点也很清楚。

header 字段位于地址:0x15F6、0x15F7 和 0x15F8。

然后第一个payload-byte在0x15FA处,0x15F9被遗漏了。

我已附上调试器中显示的 screenshot 内存。

我不明白为什么会跳过一个字节以及如何解决它。

payload 联合对齐到四字节边界,而 header 只有三个字节长。这意味着结构的 C 定义中有一个填充字节,但您的内存映射可能已打包,省略了所有填充。您需要使用特定于编译器的标志、编译指示或属性来指定打包各种 unions/structures(以一个字节对齐)以确保不会创建填充字节。例如, and .

此外,根据您的磁盘数据格式,您可能需要小心执行字节交换以从机器本机字节序(通常是小字节序,例如在 x86 上)切换到网络字节序(通常是大字节序,但以下情况除外)一些 Windows 特定协议)。