开发者

Can/do compilers simplify logical expressions involving functions?

Some functions which calculate booleans:

bool a()
{
   return trueorfalse;
}

bool b()
{
   //...
}

bool c()
{
   //...
}

This condition

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

can also be written as

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

Will compilers usually optimize this away?

And what about pure boolean values:

if((a&&b&&c) || (a&&b&&!c))
{ 
   doS开发者_StackOverflowomething();
}


Since the functions may have side effects, the conditional cannot be "optimized" in any way, since all the functions will have to be called (conditionally) in a well-defined manner.

If you do want optimization, you can assign the result to variables first:

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

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

It's possible that constexpr functions introduced in C++11 will allow for optimization if they yield a constant expression, though, but I'm not sure.

You can even condense this down: In the following code, f() has to be called twice:

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


No they won't. The reason why is that the optimization would be visible to the user because it would change the observable side effects. For example In your optimized version c() would never execute even though the user explicitly tried to do so. This can and will lead to bugs.


Since your premise a flawed, no, they won't.

(a()&&b()&&c()) || (a()&&b()&&!c()) definitely can't be rewritten as (a()&&b())

C (and C++) isn't a functional programming language (like Haskell).


But the problem is that it can't be refactored in that way, generally speaking!

If any of the functions have side effects that change the result of c() then the second call would possibly return a different result from the first one.

Not only that, but due to short-circuit execution things could be muddied even further.


Very often in C the return value of a function gives whether the function was executed successfully of not. For example calling a graphics routine, converting a file. Think how often you use pointers to change something external to the function. Or call another function that outputs something. As someone said this isn't functional programming.

If the compiler is able to determine that foo() changes and does nothing then it may by all means simplify it but I would NOT count on it.

Here is a very simple example

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;
}

Edit any boolean algebra of variables should be simplified.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜