Question

&& is a short-circuit operator evaluated from left to right, so if the operand on the left side of && operator is evaluated to false, evaluation should not continue. BUT I expected that the ++ should be evaluated before && because it has higher precedence, and (from the link):

Operators with higher precedence are evaluated before operators with relatively lower precedence.

In that case, why doesn't count increment in the third line of this code?

int mask = 2;
int count = 0;
if( !(mask > 1) && ++count > 1) { mask += 100; }
System.out.println(mask + " " + count);
Was it helpful?

Solution 2

Edit: I missed the point of the question. See revisions for semi-detailed explanation of short-circuit evaluation.

Each operand of the logical-AND and logical-OR operators is a separate expression, and thus, treated independently (given its own order of operators to evaluate, according to correct operator precedence).

So, while ++ has the highest precedence in ++count > 1, that expression is never even evaluated (because of the short-circuiting).

OTHER TIPS

No, the way the expression is evaluated goes from left to right, while taking operator precedence into account. So once in a && b the a gets false, b is not evaluated anymore.

JLS §15.23. Conditional-And Operator && says:

The conditional-and operator && is like & (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is true.


Here is a detailed step by step evaluation of how this works:

This is because, when you parse an expression as a human being, you start with the lowest precedence operators first. In this case && has lower precedence then ++.

++a < 0 && foo
        ^^
       start

In order to compute the result of &&, you should know the left operand:

++a < 0 && ++b
^^^^^^^
so compute this

Now, when you want to know the result of ++a < 0, take a look at the lowest precedence operator first, which is <:

++a < 0
    ^
   evaluate this

In order to do that, you will need both left and right operand. So compute them:

++a
0

This is the moment were ++a gets increased.

So, now we are at the bottom. Let's make our way back to the top:

false && foo

And this is where the fact that && is short circuit comes in. Left operand is false, so the right operand expression foo is not evaluated anymore. Which becomes:

false

without the evaluation of the right operand.

You seem to be dissatisfied with the short circuit evaluation explanation. Why is precedence not important here?

Imagine this code:

if( !(mask > 1) && Increment(count) > 1)

Function application (that is, calling a function by writing the brackets) is the highest precedence, yet the function call will never happen. If short circuit evaluation made allowances for precedence, it wouldn't really work at all.

To expand a little - operators such as ++ , - , etc all map to function calls. However, the compiler needs to understand the order that they bind. This is not the order that they are evaluated in.

So a + b * c doesn't mean workout b * c then the sum. It means only this add( a, multiply(b, c)) The order of evaluation is different in the case of && (though not in my example), to make it easier for programmers to write quick code.

To avoid confusion, recall that

if (a && b) {
    // do something
}

is semantically the same as:

if (a) {
    if (b) {
         // do something
    }
}

Obviously, if a evaluates to false, the term b will never be seen. In particular, an increment opertor there will not execute.

By recalling this expansion, the behaviour should be easier to understand. It's best to consider && as a shortcut for above nested-if statement. (In the case of having an else statement, you will also need to add two copies of the else code, so it's not as easy.)

A more "exact" representation would be to use a condition method:

boolean condition() {
    if (!a) return false;
    if (!b) return false;
    return true;
}

Again, b will never be evaluated if a returns false already.

if( !(mask > 1) && ++count > 1) { mask += 100; }

What this line indicates is: !(2>1) ie !(true) ie false

In && left side is false it doesnot futher go for checking rightside

so count is not incremented.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top