Salma Ihab Hamed
Salma Ihab Hamed

Reputation: 25

Evaluate Postfix and Logical Operators in C with no short-circuiting approach

I came across this question when studying logical operators and conditionals in C.

#include <stdio.h>
int main() {

    int x = 3;
    int y = 2;
    int z = 3;
    printf("Result #4 = %d\n", x++ <= 3 || y++ >= 2 && z++ != 3);
    printf("x: %d y: %d z: %d\n", x, y, z);
    return 0;

}

Output:

Result #4 = 1
x: 4 y: 2 z: 3

I do not understand the last line of output. The values for x, y, z do not match my understanding.

Here is my line of thought.

I tried to find the reference textbook or worksheet from which this question was taken, but I was not able to. I did some research on StackOverflow and I don't think this is a short-circuited condition. If it were, I don't understand why.

The only explanation I can come up with is that the x value will have the side effect implemented (x incremented) because it is evaluated as true, while the rest of the OR statement will not have its side effects since it is evaluated as false, therefore y and z will not be incremented. Is this the case?

Upvotes: 1

Views: 81

Answers (3)

Vlad from Moscow
Vlad from Moscow

Reputation: 311088

You correctly wrote that

The expression x++ <= 3 || y++ >= 2 && z++ != 3 will be evaluated like : x++ <= 3 || (y++ >= 2 && z++ != 3).

Now let's read the C Standard about the logical OR operator (the C23 Standard, 6.5.14 Logical OR operator):

3 The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it yields 0. The result has type int.

4 Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; if the second operand is evaluated, there is a sequence point between the evaluations of the first and second operands. If the first operand compares unequal to 0, the second operand is not evaluated.

So as the first operand that is the expression x++ <= 3 evaluates to logical true (its result is equal to 1) then the second operand (y++ >= 2 && z++ != 3) does not evaluate. It means that the variables y and z stay unchanged.

Pay attention to that (6.5.8 Relational operators):

7 Each of the operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false.119). The result has type int.

and secondly (6.5.2.4 Postfix increment and decrement operators):

2 The result of the postfix ++ operator is the value of the operand. As a side effect, the value of the operand object is incremented (that is, the value 1 of the appropriate type is added to it).

That is in the first operand of the logical OR operator there are compared the value of the variable x before its increment that is equal to 3 with the integer constant 3. And in the next printf statement there will be outputed already incremented variable x.

Upvotes: 2

0___________
0___________

Reputation: 67835

This expression is evaluated this way:

int result;
if(x++ <= 3)
{ 
    result = true
}
else
{
    result = false;
    if(y++ >= 2)
    {
        if(z++ != 3) 
        {
           result = true;
        }
    }
}   

Upvotes: 1

3CxEZiVlQ
3CxEZiVlQ

Reputation: 38863

The expression x++ <= 3 || y++ >= 2 && z++ != 3 will be evaluated like : x++ <= 3 || (y++ >= 2 && z++ != 3).

If you think in terms of parentheses then why do you apply them at the right side only and not at the other side? The expression would be rather evaluated like (x++ <= 3) || (y++ >= 2 && z++ != 3).

Why do you assume that the right side is evaluated first? Equal parts are evaluated through left to right.

int x = 3 and x++ <= 3 is evaluated first: 3 <= 3 is true and x gets 4. The right side is not evaluated, y and z keep their initial values.

Upvotes: 2

Related Questions