C语言关于&与&&运算符

C语言关于&与&&运算符

我们知道,在很多场景中&和&&通常可以相互代替,那么它们到底有什么不同呢?

先看一段代码

cpp 复制代码
bool a, b, c;
c = a & b;

使用clang++ -S编译出来的指令如下:

asm 复制代码
	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编译出来的指令如下:

asm 复制代码
	movzbl	-1(%rbp), %edx
	andb	-2(%rbp), %dl

再看一段代码:

cpp 复制代码
bool a, b, c;
c = a && b;

其汇编代码为:

asm 复制代码
    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

反汇编一下:

cpp 复制代码
tmp = a;
if(a==1) {
    tmp = b;
}
c = tmp & 1;

通过对比两段汇编代码就很清晰了,&运算在底层表现为一条指令and,而&&运算实际上需要通过分支的方式实现。

那么能否说明&的效率比&&要高呢?不一定

我们知道,&是与运算,例如要得到a & b的值,就必须分别求得a和b的值。但是&&通过分支的方式实现,要想得到a && b的值,其实不必都求出a和b的值,如果先求出a的值是0,那么就不必再求b了。

再看一段代码:

cpp 复制代码
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

相关推荐
yaoxin5211238 小时前
434. Java 日期时间 API - Period 基于日期的时间段
java·开发语言·python
凡人叶枫8 小时前
Effective C++ 条款30:透彻了解 inlining 的里里外外
linux·开发语言·c++·嵌入式开发·effective c++
noipp8 小时前
推荐题目:洛谷 P10907 [蓝桥杯 2024 国 B] 蚂蚁开会
c语言·c++·算法·编程·洛谷
学逆向的8 小时前
C++纯虚函数
开发语言·c++·网络安全
程序员二叉9 小时前
【JUC】ThreadLocal底层原理|内存泄漏|弱引用|跨线程传递方案
java·开发语言·面试·职场和发展·juc
程序员二叉9 小时前
【JUC】线程池全套深度详解|参数|流程|拒绝策略|调优|异常处理
java·开发语言·jvm·算法·面试·juc
凡人叶枫10 小时前
Effective C++ 条款22:将成员变量声明为 private
linux·开发语言·c++
Qt程序员10 小时前
掌握 Linux 内核调度:从原理到实现(进程篇)
java·开发语言
code bean10 小时前
【LangChain】检索器完全指南:从向量检索到生产级 RAG 架构
java·开发语言·微服务
LabVIEW开发10 小时前
LabVIEW + MATLAB 混合编程:爆炸场测试数据精准采集方案
开发语言·matlab·labview