我们知道,在很多场景中&和&&通常可以相互代替,那么它们到底有什么不同呢?
先看一段代码
bool a, b, c;
c = a & b;
使用clang++ -S编译出来的指令如下:
movb -5(%rbp), %al # a
andb $1, %al
movzbl %al, %eax
movb -6(%rbp), %cl # b
andb $1, %cl
movzbl %cl, %ecx
andl %ecx, %eax # a & b
cmpl $0, %eax
setne %al
andb $1, %al
movb %al, -7(%rbp) # c
使用clang++ -S -O3编译出来的指令如下:
movzbl -1(%rbp), %edx
andb -2(%rbp), %dl
再看一段代码:
bool a, b, c;
c = a && b;
其汇编代码为:
xorl %eax, %eax
testb $1, -5(%rbp) # a
movb %al, -8(%rbp)
je .LBB2_2
# %bb.1:
movb -6(%rbp), %al # b
movb %al, -8(%rbp)
.LBB2_2:
movb -8(%rbp), %al
andb $1, %al
movb %al, -7(%rbp) # c
反汇编一下:
tmp = a;
if(a==1) {
tmp = b;
}
c = tmp & 1;
通过对比两段汇编代码就很清晰了,&运算在底层表现为一条指令and,而&&运算实际上需要通过分支的方式实现。
那么能否说明&的效率比&&要高呢?不一定
我们知道,&是与运算,例如要得到a & b的值,就必须分别求得a和b的值。但是&&通过分支的方式实现,要想得到a && b的值,其实不必都求出a和b的值,如果先求出a的值是0,那么就不必再求b了。
再看一段代码:
bool funcA() {
}
bool funcB() {
}
int main () {
bool c = funcA() & funcB();
bool d = funcA() && funcB();
}
上述代码中表达式funcA() & funcB() 与 funcA() && funcB() 哪一个效率更高?
需要具体分析funcA()和funcB()的返回值分布与复杂度,如果funcA()和funcB()复杂度很低,并且大部分情况下返回1,那么funcA() & funcB()的效率可能会高些;如果funcA()和funcB()复杂度较高,并且有可能返回0,那么funcA() && funcB()会高一些。
另外值得一提的是,funcA() && funcB()与funcB() && funcA()哪个效率高?
返回0概率 | 复杂性(耗时) | |
---|---|---|
funcA() | a_pz | a_cost |
funcB() | b_pz | b_cost |
funcA() && funcB() 期望耗时为:
a_cost + (1-a_pz) * b_cost
funcB() && funcA() 期望耗时为:
b_cost + (1-b_pz) * a_cost
举个例子
返回0概率 | 复杂性(耗时) | |
---|---|---|
funcA() | 0.9 | 50 |
funcB() | 0.8 | 40 |
funcA() && funcB() 期望耗时为54; funcB() && funcA() 期望耗时为50