4

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";
Zubair
  • 5,833
  • 3
  • 27
  • 49
  • you don't need the parenthesis that is there, but depending on the operator precedence (I cannot remember it) you may need parenthesis aroudn the `remainder & 1` sub-expression. – Cheers and hth. - Alf Nov 11 '14 at 05:43
  • See [C++ operator precedence](http://en.cppreference.com/w/cpp/language/operator_precedence) – Remy Lebeau Nov 11 '14 at 05:47

2 Answers2

13

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.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • Which only works if the compiler implements boolean expression short-curcuiting to skip `std::cout << "odd"` if `remainder & 1` evaluates to false. Without a short-curcuit, both `cout << "odd"` and `cout << "even"` would likely be evaluated. – Remy Lebeau Nov 11 '14 at 05:50
  • 6
    @RemyLebeau If the compiler doesn't implement boolean short-circuiting then [it is not a conforming C++ compiler](http://stackoverflow.com/questions/628526/is-short-circuiting-boolean-operators-mandated-in-c-c-and-evaluation-order). – cdhowie Nov 11 '14 at 05:52
  • @cdhowie: your explanation is more value-able. – Zubair Nov 11 '14 at 06:01
  • 3
    "Assuming that this operation succeeds" - that is a good caveat to take note of, because `operator<<` *can* fail (albeit unlikely), so if `cout << "odd"` fails, `cout << "even"` will be evaluated even though `remainder & 1` is true. – Remy Lebeau Nov 11 '14 at 06:05
  • +1, but while I agree that the case at hand is an abuse of notation, there are cases where at least the `||` part here makes sense also in C++. E.g. I often write `hopefully( something ) || fail( "blah" )`. The Windows *cmd.exe* command interpreter is one example where the notation in some cases is required, because it's pretty arbitrary which commands set proper exit codes or not, but still for internal command the command interpreter knows about success and failure. – Cheers and hth. - Alf Nov 11 '14 at 06:08
  • @RemyLebeau Right, but if it fails to write one I don't see it succeeding to write the other, which is why I didn't bring it up in an already fairly wordy answer. – cdhowie Nov 11 '14 at 07:04
6

The line in question:

(remainder & 1 && std::cout<<"odd" ) || cout<<"even";

Is the same as the following when you take operator precedence and operator overloads into account:

((remainder & 1) && (operator<<(std::cout, "odd").operator bool())) || (operator<<(std::cout, "even").operator bool());

std::cout (more generically, std::basic_ostream) has operator<<() and operator bool() operators defined. The first operator returns a std::basic_ostream& reference, ie a reference to the stream itself (useful for chaining operations together). The second operator returns whether the stream is in a failure state or not.

See the following documentation for more details:

C++ operator precedence

operator overloading

std::basic_ostream::operator<<

std::basic_ios::operator bool

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770