Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What logical AND operation does with stream output?

Tags:

c++

c++11

I just saw the code and I am unable to understand how the logical and behaves with "cout" here:

int userInput = 9; // Suppose user input is 9.
int remainder = 9 % 2;
(remainder & 1 && std::cout<<"odd" )|| cout<<"even";
like image 978
Zubair Avatar asked Dec 01 '22 18:12

Zubair


1 Answers

std::cout<<"odd" is an expression that will return std::cout (which is why you can do std::cout << a << b << c). When evaluated in boolean context, it simply returns true if the fail bit isn't set. So if the output operation succeeds then it will evaluate as true.

However, the intent of this code isn't to test that value, rather it is a clever (and not very readable)1 way to express this:

if (remainder & 1) {
    std::cout << "odd";
} else {
    std::cout << "even";
}

It takes advantage of the short-circuiting nature of the && and || operators:

  • In a && b, if a is false then it evaluates as a (b is not evaluated!) otherwise it evaluates as b.
  • In a || b, if a is true then it evaluates as a (b is not evaluated!) otherwise it evaluates as b.

So if remainder & 1 evaluates as false (zero in this case) then std::cout << "odd" is not evaluated because the && expression short-circuits, returning false. This is the left operand to the outer || expression, which causes its b (std::cout << "even") to be evaluated, writing "even" to the output.

If remainder & 1 evaluates as true (non-zero in this case) then the right operand for && is evaluated, displaying "odd". Assuming that this operation succeeds, the left operand for the || operation will be true, which causes it to short-circuit and not evaluate the right operand.


1 Experienced programmers are likely to know exactly what is going on here, but as you have found this technique is not the most readable. It's better (IMO) to be straightforward about the intent of code, so I would just use an if conditional -- or, at the very least, use the ternary operator: std::cout << (remainder & 1 ? "odd" : "even").

In other languages (JavaScript comes to mind) (ab)using the short-circuiting operators is a very common technique. I usually don't see them used this way in C++ and I would strongly discourage such use.

like image 123
cdhowie Avatar answered Dec 04 '22 03:12

cdhowie