可以/做编译器简化涉及函数的逻辑表达式吗?

时间:2011-09-01 18:23:33

标签: c++ c compiler-optimization

计算布尔值的一些函数:

bool a()
{
   return trueorfalse;
}

bool b()
{
   //...
}

bool c()
{
   //...
}

这个条件

//somewhere else
if((a()&&b()&&c()) || (a()&&b()&&!c()) )
{
    doSomething();
}

也可以写成

if(a()&&b())
{
   doSomething();
}

编译器通常会优化它吗?

纯粹的布尔值怎么样:

if((a&&b&&c) || (a&&b&&!c))
{ 
   doSomething();
}

5 个答案:

答案 0 :(得分:4)

由于函数可能有副作用,因此无法以任何方式“优化”条件,因为必须以明确定义的方式(有条件地)调用所有函数。

如果您确实需要优化,可以先将结果分配给变量:

const bool ba = a(), bb = b(), bc = c();

if (ba && bb && bc || ba && bb && !bc) { /* ... */ } // probably optimized to "ba && bb"

C ++ 11中引入的constexpr函数可能会在它们产生常量表达式时进行优化,但我不确定。

你甚至可以压缩它:在下面的代码中,f()必须被调用两次:

if (f() && false || f() && true)
{
  // ...
}

答案 1 :(得分:2)

不,他们不会。原因是用户可以看到优化,因为它会改变可观察的副作用。例如,在优化版本c()中,即使用户明确尝试这样做,也永远不会执行。 可以而且会导致错误。

答案 2 :(得分:1)

由于你的前提是有缺陷的,不是,他们不会。

(a()&&b()&&c()) || (a()&&b()&&!c())绝对不能改写为(a()&&b())

C(和C ++)不是函数式编程语言(如Haskell)。

答案 3 :(得分:1)

但问题是,不能以这种方式重构,一般来说!

如果任何一个函数的副作用改变了c()的结果,那么第二个调用可能会返回与第一个函数不同的结果。

不仅如此,由于短路执行,事情可能会更加混乱。

答案 4 :(得分:1)

通常在C中,函数的返回值表示函数是否成功执行了。例如,调用图形例程,转换文件。想想你经常使用指针来改变函数外部的东西。或者调用另一个输出内容的函数。有人说这不是函数式编程。

如果编译器能够确定foo()发生了变化并且什么也没做,那么它可能无论如何都会简化它,但我不会指望它。

这是一个非常简单的例子

bool foo()
{
    std::cout << "this needs to be printed each time foo() is called, even though its called in a logical expression\n";
    return true;
}

int main()
{
    if ((foo() && !(foo()) || foo() && !(foo())))
        return 0;

    return 1;
}

编辑任何变量的布尔代数都应该简化。