7

Let's say I had two functions and a variable,

int number;

bool foo (void);
bool footoo (void);

And in each of these functions, some logic with the variable number takes place, such as:

number++;
return(rand()%2);

And then I call them like so:

if (foo() && footoo())
{
    cout << "Two foo true!"
}

Why aren't both functions being called and how can I guarantee both functions are called and increment number, regardless of return value?

Wolf
  • 9,679
  • 7
  • 62
  • 108
James Hurley
  • 833
  • 1
  • 10
  • 33
  • 2
    You might as well keep it simple and readable: `bool b1 = foo(); bool b2 = footoo(); if (b1 && b2 ) { /* ... */ }` – jrok Jul 30 '13 at 20:25
  • 1
    possible duplicate of [How does C++ handle &&? (Short-circuit evaluation)](http://stackoverflow.com/questions/5211961/how-does-c-handle-short-circuit-evaluation) –  Jul 30 '13 at 20:30
  • `if (foo() + footoo() == 2) cout << "Two foo true!";` – Pete Becker Jul 31 '13 at 17:28
  • If you return bool use single & and both will be called. – andz Jul 25 '22 at 20:51

6 Answers6

10

In C (and included in C++ by default) the && operator is short-circuiting. This means that as soon as the condition is deemed false the other operand is not evalulated. It allows us to do things like if(ptr && ptr->value == 10) without having to do the pointer validity check before the value check in a separate if statement.

If you want to run both functions, run both functions and save off the results:

bool b = foo();
if(foobar() && b)
{
    // Stuff
}
Mark B
  • 95,107
  • 10
  • 109
  • 188
3

Simplest thing I can think of: Assign the return values of both to variables and check those:

bool fooIsTrue = foo();
bool footooIsTrue = footoo();
if(fooIsTrue && footooIsTrue)
    // ...

They aren't being called right now because && short-circuits, that is, when the left is false the whole expression is sure to be false so the right side is skipped.

This is useful for constructions where for example you want to first check if you can access something before you check it like so:

if(somePtr != NULL && somePtr[0] == 1)
confusopoly
  • 1,245
  • 7
  • 19
2

Why aren't both functions being called? It's called "short-circuit evaluation" and is an efficiency feature of C++. The rationale (roughly) is that code called in the context of a test is generally side-effect-free, and therefore if you can establish that the test is going to fail by only evaluating the leftmost expression, you should do so.

Your code is not side-effect-free, so short-circuit evaluation is not a feature that helps you in this case.

In order to guarantee both functions are called, you'll need to call them separately from the test of their return values:

bool fooRet = foo();
bool footooRet = footoo();

if (fooRet && footooRet)
{
    cout << "Two foo true!"
}
mwigdahl
  • 16,268
  • 7
  • 50
  • 64
  • Although true, I could in fact use the bitwise to be side effect-free. – James Hurley Jul 30 '13 at 20:38
  • 1
    That's not really what I'm talking about -- a function that makes changes to data has side-effects; one that simply performs comparisons and returns and answer is side-effect free. Your functions make changes, so they have side-effects, and it isn't a good idea to test them using short-circuit operators if you need them called no matter what. – mwigdahl Jul 30 '13 at 20:45
  • 1
    @JimHurley I wouldn't use the bitwise and, it would make the code confusing to an outside user, also there can still be side effects – aaronman Jul 30 '13 at 20:45
  • Thanks guys, I've edited my code accordingly. I had no idea it was so wrong to use bitwise operators like this. – James Hurley Jul 31 '13 at 03:44
1

&& and || are what we call short circuit operators. What this means is that if by evaluating the first argument we can tell the truthiness of the whole expression we stop and don't evaluate the next expression.

For example if in this statement a && b is a is false we know the whole statement cannot be true and thus it is ok to stop. With || we can stop if the first statement is true.

If you want both functions to be called the first one must return a value that can be evaluated as true. You can do this if you want both to be called.

bool a = foo();
bool b = footoo();
if (a && b)
{
    cout << "Two foo true!"
}

This way both are called.

In C++ bool's are guaranteed to be a 1 or 0 so the bitwise operators are actually the same as the short circuit it terms of the result. However I would not use them for readability.

aaronman
  • 18,343
  • 7
  • 63
  • 78
1

In an if statement where && is involved (something like if (a && b && c && d)), if the 1st condition is false, then the rest of the condition in the if isn't evaluated anymore and the false "block" is executed.

The same thing happens with ||. If you have if (a || b || c || d) and a is true, then the rest of the condition isn't evaluated and the true "block" is executed.

If you want both of them to be called, just assign them to two boolean variables like bool myB1 = foo(), myB2 = footoo(); and then do if (myB1 && myB2).

Iosif Murariu
  • 2,019
  • 1
  • 21
  • 27
-1

Becasue with statement if(first && second) , if first is not true, second is not even checked.

tomi.lee.jones
  • 1,563
  • 1
  • 15
  • 22
  • No, there is no answer to that in a question, and the statement "when first is false seconds is not checked" due to already known logical value of conjuction is exactly the answer to the OP's question, but thanks for the downvote, you really contribute. – tomi.lee.jones Jul 31 '13 at 15:27
  • I am the OP. But my bad, the answer is not stated in the question. However, it fails to answer both questions, and has less information then the rest of the answers provided. -1. – James Hurley Jul 31 '13 at 15:59