当我请求或设置逐位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
以获得此优势?
答案 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
这为您提供了混合的汇编和源代码。