在 C++ 结构体中打包位字段时遇到困难

问题描述 投票:0回答:1

我试图制作一种更好的类型来处理发送到 LED 驱动器 IC 的打包数据。格式看起来像这样。它显示两种可能的格式,具体取决于

Address
位的值。请注意,MSB 显示在右侧,而不是左侧,并且应该是移入 IC 的第一位:

Allegro A6281 register format diagram

我尝试编写一个联合类型来解决这个问题,但它不断扩展到 5 个字节。所以我决定尝试写这个:

struct Color {
    uint8_t     ignore  :   1;
    uint8_t     address :   1;
    uint16_t    red     :   10;
    uint16_t    green   :   10;
    uint16_t    blue    :   10;

    Color()
        :
        ignore(0),
        address(0),
        red(0),
        green(0),
        blue(0)
    {
    }
} __attribute__((packed));

从结构体的开头按顺序转储字节(在 M1 MacBook Pro 上,用 Clang 编译,所以是小端)给我:

Color c;
c.ignore = 1;
dump(&c, sizeof(c));

01 00 00 00 

我期待

80 00 00 00
。如果我将
address
ignore
放在结构体的末尾,我会得到
00 00 00 80
,这也是意料之外的。

是否可以编写这样的类型,使所有位都按照预期的顺序打包到 4 个字节中?我意识到在分配给

uint16_t
值时也可能存在字节序问题,但我认为我可以处理这个问题。

c++ bit-fields
1个回答
0
投票

为此,您不应该使用位字段,而应该使用位移位和位屏蔽。遗憾的是,位字段因编译器而异,您不能依赖正确的字节顺序。

如 C99 标准 6.7.2.1:10 所述:

实现可以分配任何足够大的可寻址存储单元来容纳位字段。如果还有足够的空间,则紧接着另一个位字段的位字段 结构应打包到同一单元的相邻位中。如果剩余空间不足, 不适合的位域是否被放入下一个单元或与相邻单元重叠 实现定义的。单元内位域的分配顺序(高位到 低阶或低阶到高阶)是实现定义的。的对齐方式 可寻址存储单元未指定。

© www.soinside.com 2019 - 2024. All rights reserved.