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

时间:2015-05-07 18:55:28

标签: c++ bit-manipulation unions bit-fields

当我请求或设置逐位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
}

我认为后者会快得多,因为它的操作次数只有一半。

如果后者 为真,我是否必须将位字段成员声明为类型bool以获得此优势?

2 个答案:

答案 0 :(得分:2)

编译器会将您的位操作转换为完成作业所需的任何按位和/或/不操作系列。

e.g。

s.flag1 = 1;

会变成

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

并且分配的实际值取决于您正在编译的特定CPU的位/字节顺序。

答案 1 :(得分:0)

您的问题一般无法回答。每个编译器都可以自由决定如何实现位域。不能保证它先是高位或低位。这可能取决于系统的结束,但也不能保证。因此,对比特字段使用联合转换绝对不可移植!

编译器可以生成的代码取决于编译器和为其创建代码的cpu。例如,如果您想测试并设置一些位,则某些cpu架构支持单个操作码/指令。另一个cpu可能只能检查lsb,所以它必须移动n次以捕获你想要的位。其他一些cpu可以使用和/或组合。

简单回答:这取决于: - )

但几乎可以保证现代编译器会尽力生成最小或禁用的代码,这些代码可以在选定的cpu上完成工作。

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

在Linux上你可以使用: objdump -S a.out 这为您提供了混合的汇编和源代码。

相关问题