使用和操作员进行微优化

micro optimisation using and operator

本文关键字:优化 操作员      更新时间:2023-10-16

假设这种情况,你有一个返回void的函数,该方法主要是if的唯一语句

if(condition)
    someVoidMethod();

由于某些语言不会继续评估串联和的布尔表达式,如果其中任何一个返回 false。我们想知道将返回类型更改为 int(或布尔/布尔值)并编写它所暗示的优化是什么

condition && someIntMethod();

没有任何分配。

我们知道程序员不应该专注于微优化,但这实际上只是出于学术目的。

编译器将为具有任何合理优化级别的两种备选方案生成相同的代码。这两个语句背后的逻辑完全相同,因为&&在 C 和 C++ 中都会产生短路的分支行为。

我使用两个程序验证了这一点:

计划1:

#include <stdio.h>
int foo() {printf("foon");}
int main() {
    int i;
    scanf("%d", &i); // Prevent from optimizing out the "if"
    if (i) foo();
    return 0;
}

计划2:

#include <stdio.h>
int foo() {printf("foon");}
int main() {
    int i;
    scanf("%d", &i); // Prevent from optimizing out the "if"
    i && foo();
    return 0;
}

我在 mac 上用 -O3 级别 * 编译了这两个程序,并比较了输出:

gcc -c -O3 a.c
gcc -c -O3 b.c
cmp a.o b.o

cmp没有产生任何输出,因此文件是相同的。没有 -O3 标志的编译会产生不同的输出。


* gcc --version命令打印

Apple LLVM 5.0 (clang 500.2.79) (based on llvm 3.3svn)

需要一个

更聪明的编译器才能弄清楚它可以忽略someIntMethod的返回值(尽管我怀疑大多数编译器都会这样做)。但更严重的是,如果函数没有inline即使它将被丢弃,也必须花费额外的周期才能将值传回,因此第一个可能更有效率。

也就是说,确定的唯一方法是使用编译器和与发布版本一致的选项进行编译,并查看它生成的程序集。