【发布时间】:2016-01-28 08:22:03
【问题描述】:
我有以下三个联合:
typedef union {
struct {
uint16_t : 2;
uint16_t numberOfWords : 10;
uint16_t : 4;
uint16_t dataFormat : 8;
uint16_t : 8;
} bf;
uint32_t dw;
} HeaderT;
typedef union {
struct {
uint16_t : 4;
uint16_t lsb : 8;
uint16_t : 4;
uint16_t msb : 8;
uint16_t : 8;
} bf;
uint32_t dw;
} RegisterT;
typedef union {
struct {
uint16_t : 2;
uint16_t lsb : 10;
uint16_t : 2;
uint16_t msb : 10;
uint16_t : 8;
} bf;
uint32_t dw;
} BinT;
我得到 sizeof(HeaderT) == 4,sizeof(RegisterT) == 4,但 sizeof(BinT) == 8!我不知道为什么。
在做
typedef union {
struct {
uint16_t : 2;
uint16_t lsb : 10;
uint16_t : 2;
uint16_t msb : 10;
uint16_t : 8;
} bf __attribute__((packed));
uint32_t dw;
} BinT;
没有帮助。我需要 BinT 为 32 位宽;它被内存映射到 FPGA 上的一堆寄存器。
有人知道发生了什么吗?我在 ARMv7 上使用 gcc。但是,我在 x86_64 VirtualBox VM 上的 gcc 上看到了相同的情况。
谢谢。
【问题讨论】:
-
好的,所以通过将 uint16_t 的全部更改为无符号,我得到了预期的结果。不过,我不明白为什么。类型不是仅在从位字段读取时才相关[假设类型足够宽],例如,如果您从 uin16_t 位字段读取,您会得到一个包含这些位的 uint16_t?
-
因为您使用
uint16_t,单个位域中的位不能超过 16 位的边界。BinT的前 3 个字段中使用了 14 位,因此接下来的 10 位不适合 16,因此它为msb中的 10 位启动一个新的uint16_t。然后 8 个匿名位在 10 之后不适合,所以你有第三个uint16_t单元。把最后一组uint16_t改成uint32_t就OK了。