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

时间:2016-06-16 12:43:02

标签: c memory-management struct padding unions

有点令人困惑的标题,我知道。

我创建了一个包含“raw”-array和2个结构的联合。这两个结构包含一个struct 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;

现在,当我运行代码时,头字节的内存映射很好。 raw数组的byte [0]映射到header-struct中的len-field。 cmd0和cmd1也是如此。但是,afRegisterSRSP-struct的“status”不是指向状态字节,而是指向CRC-Byte,它位于状态字节之后。查看内存地址时也很清楚。

标题字段位于地址:0x15F6,0x15F7和0x15F8。

然后第一个有效载荷字节位于0x15FA并且省略了0x15F9。

我已经附加了调试器中显示的screenshot内存。

我无法弄清楚为什么跳过一个字节以及如何解决它。

1 个答案:

答案 0 :(得分:1)

payload联合与四字节边界对齐,header只有三个字节长。这意味着在结构的C定义中有一个填充字节,但是你的内存映射可能是打包的,省略了所有填充。您需要使用编译器特定的标志,pragma或属性来指定各种联合/结构被打包(到一个字节对齐)以确保不创建填充字节。例如,gcc packingVisual Studio packing

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