如何处理位字段中的单位(布尔)成员?

How are single-bit (boolean) members in bit fields handled?

当我请求或设置按位 struct/class 的单位成员时,编译器会进行位移吗?例如,给定此 struct:

struct {
    unsigned char thing : 4;
    unsigned char flag1 : 1;
    unsigned char flag2 : 1;
    unsigned char reserved : 2;
}

...编译器是否意识到不需要移位?也就是说,编译器是不是这样做的:

uchar request_flag1() const {
    uchar temp = data & 0x40;       //0100 0000 - get the 7th bit
    return temp >> 7;               //0000 0001 - return the shifted value
}
void set_flag1(uchar v) {
    data &= 0x191;                  //1011 1111 - clear the 7th bit
    data |= v << 7;                 //0v00 0000 - set the 7th bit to shifted value
}

还是这个?

bool request_flag1() const {
    return data & 0x40;             //0100 0000 - simply check whether the 7th bit is set
}
void set_flag1(bool v) {
    if(v) data |= 0x40;             //0100 0000 - simply set the 7th bit
    else data &= 0x191;             //1011 1111 - simply clear the 7th bit
}

我想后者会明显更快,因为它是操作次数的一半。

如果后者 true,我是否必须将位域成员声明为 bool 类型才能获得此优势?

编译器会将您的位操作转换为完成任务所需的任何一系列 bitwise-and/or/not 操作。

例如

s.flag1 = 1;

会变成

s = s | 00000010;
        ^^^^^^-----stuff
              ^----flag1
               ^---flag2

并且分配的实际值将取决于您正在编译的特定 CPU 的 bit/byte 顺序。

您的问题无法笼统回答。每个编译器都可以自由决定如何实现位域。不能保证是高位在前还是低位在前。这可能取决于系统的端点,但也不能保证。所以用union转换bit-field肯定是不可移植的!

编译器可以生成的代码取决于编译器以及它必须为其创建代码的cpu。例如,如果你想测试和设置一些位,一些 cpu 架构支持一个 opcode/instruction 完全用于该用途。另一个 cpu 可能只能检查 lsb,所以它必须移动它 n 次才能捕捉到你想要的位。其他一些 cpu 可能与 and/or 组合一起使用。

简单回答:视情况而定:-)

但几乎可以保证现代编译器将尽最大努力生成可以在选定 cpu 上完成工作的最小或快速代码。

如果您真的想知道您的编译器生成了什么,只需查看生成的程序集即可。

在 linux 您可以使用: objdump -S a.out 这使您的程序集和源代码混合在一起。