我有以下三个工会:
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;
Run Code Online (Sandbox Code Playgroud)
我得到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;
Run Code Online (Sandbox Code Playgroud)
没有帮助.我需要BinT为32位宽; 它的内存映射到FPGA上的一堆寄存器.
有谁知道发生了什么?我在ARMv7上使用gcc.但是,我在x86_64 VirtualBox VM上的gcc上看到了相同的内容.
谢谢.
位字段成员不能拆分为两个(或更多)基元.那么,就标准而言,根本不保证包装.它的实现已定义.但这是一个典型的限制,如果实现确实打包位字段.
让我们看看GCC手册中有关实现定义行为的内容:
- 位域是否可以跨越存储单元边界(C90 6.5.2.1,C99和C11 6.7.2.1).
由ABI决定.
我不确定这是否适用于ARM,但通常GCC符合64位Itanium规范.
(假设从左到右打包)原语之间的"位分布"现在是:
uint16_t: 2 10 2 // 10 won't fit anymore
uint16_t: 10 // 8 won't fit anymore
uint16_t: 8
Run Code Online (Sandbox Code Playgroud)
这三个uint16_t
不可能适合32位.
这个:
union BinT {
struct {
uint32_t : 2;
uint32_t lsb : 10;
uint32_t : 2;
uint32_t msb : 10;
uint32_t : 8;
} bf;
uint32_t dw;
};
Run Code Online (Sandbox Code Playgroud)
从现在开始工作所有位字段都可以共享一个原语.
好的,所以通过将uint16_t改为无符号,我得到预期的结果.但我不明白为什么
unsigned
然后看起来是32位宽.
我需要BinT为32位宽
鉴于此要求,如果您希望程序可移植,则可能应避免使用位字段.如果使用位字段,则依赖于实现定义的行为.
归档时间: |
|
查看次数: |
487 次 |
最近记录: |