Boolean expression with integer increments gives unexpected results - c

#include <stdio.h>
int main()
{
int x, y, z;
x=y=z=1;
z = ++x || ++y && ++z;
printf("%d, %d, %d", x, y,z);
return 0;
}
I am getting output 2, 1, 1. I need and explanation why Y is 1 in output?

The || operator is short-circuiting; the right operand is not evaluated (and side effects never executed, i.e. the variables never incremented) if the left operand evaluates to != 0.
(Remember that "multiplication comes before addition", or in boolean logic AND comes before OR. Because of the operator precedences the expression becomes, fully bracketed, (++x) || ((++y) && (++z)); in other words, everything to the right of || is the OR's ignored right hand side.)
The evaluation of the left operand ++x increments x to 2. z is assigned the boolean value of the result of || which is 1, as it was all along.
As an aside, gcc warned and I think it is true that the statement is also undefined behavior. The C 11 standard draft n1570 says in 6.5/2:
If a side effect on a scalar object is unsequenced relative to [...]
a value computation using the value of the same scalar
object, the behavior is undefined.
The standard gives the example of i = ++i + 1; for this. In your right hand side expression z plays that role. The side effect is the increment, the value computation is the && sub-expression.
1 It is possible (i.e. I'm not sure) that it is defined as long as the right hand side is never evaluated. In that case the compiler would be allowed to assume that ++x is never 0 and omit the test. The generated code for the complicated boolean expression would just boil down to an increment of x.

The part || ++y && ++z is not evaluated, because ++x is already true. See
Short circuit evaluation

The logical operation || is so-called "short-circuit" or "lazy" operation.
If the left operand of such an operator is evaluating to logical true or a non-zero, the right operand won't be evaluated.
So in your case:
z = ++x || ++y && ++z;
++x is evaluating to 2, making x equal 2. This is non-zero, so everything on the right side is not evaluated, so y and z are not incremented. And z is assigned by the result of the logical OR operation, i.e. 1. And this is what you see.

Related

Why isn't the variable being incremented?

Increment operator not working.
I was learning C language expressions. I've also tried different combinations of increment operators (prefix and postfix) on the variables but the output is coming out to be same.
int i=-3, j=2 ,k=0,m;
m=++i&&++j||++k;
printf("%d%d%d%d\n",i,j,k,m);
I expect the output to be -2311 but it comes out to be -2301.
i and j are incremented because i needs to be evaluated. j also needs to be evaluated because i is non-zero.
But since this combined expression is non-zero, || short-circuits, and k++ is not evaluated or executed.
On the other hand, bitwise operators don't short-circuit. They also don't convert to booleans. If you want to evaluate all conditions and keep the same result you could write
m= (!!++i) & (!!++j) | (!!++k);
using the double negation trick to convert integer value to boolean.
Or spare another statement and simplify to (courtesy from user694733):
++i; ++j; ++k;
m = i && j || k;
The && and || operators short-circuit - depending on the value of the left-hand side of the expression, the right hand side may not be evaluated at all.
For the expression a || b, if a is non-zero, then the result of a || b is 1 regardless of the value of b, so b is not evaluated. For the expression a && b, if a is zero, then the result of a && b is zero regardless of the value of b, so b is not evaluated.
In your case, the result of ++i && ++j is non-zero, so ++k is not evaluated.

Logical operators' precedence in C [duplicate]

This question already has answers here:
Precedence of && over || [duplicate]
(4 answers)
Closed 4 years ago.
#include <stdio.h>
int main(void) {
int a = 0, b = 0, c = 0;
++a || ++b && ++c;
printf("%d %d %d", a, b, c);
return 0;
}
The outputs are 1, 0, 0 by gcc 8.1.0. The &&‘s precedence should higher than ||.
Why are the b and c are still 0?
The expression ++a || ++b && ++c is grouped as ++a || (++b && ++c). But, the right hand side of || is only evaluated if ++a is 0, which it isn't.
There are three issues here:
Order of precedence.
Order of evaluation.
Short circuiting of logical operators.
Order of precedence implies that ++a || ++b && ++c is evaluated as ++a || (++b && ++c).
However, due to the short circuiting requirements of logical operators, ++a is evaluated first. Only if that evaluates to false will (++b && ++c) be evaluated. In your case, ++a evaluates to true. Hence, (++b && ++c) is never evaluated.
The logical OR operator || (as well as the logical AND operator &&) is one of the few operators that perform short circut operation.
Section 6.5.14 of the C standard says the following about the logical OR operator:
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.
Because ++a evaluates to 1, the result of the || operator is guaranteed to be 1 and the right hand side is not evaluated. Also, because && has higher precedence than ||, the right side of the || operator is ++b && ++c, meaning that neither ++b or ++c is evaluated.
Precedence only controls how expressions are parsed, not how they are evaluated. Arithmetic * has higher precedence than +, so a * b + c is parsed as (a * b) + c. However, each of a, b, and c may be evaluated in any order. The result of a * b must be known before it can be added to the result of c, but that doesn't mean that a * b must be evaluated before c.
Secondly, unlike most operators in C, the || and && operators force left-to-right evaluation. An expression like a || b && c will be parsed as a || (b && c), but a will always be evaluated first, and b && c will only be evaluated if the result of a is 0.
As far as precedence goes, x || y && z acts just like x + y * z: the second operator binds more tightly than the first one, and those expressions are equivalent to x || (y && z) and x + (y * z), respectively.
The reason that b and c in the question aren't incremented is because, in addition to precedence, logical operations short circuit: once you've gotten far enough along to know the result, the rest of the expression is skipped. Both || and && evaluate their arguments left-to-right, so in a() || b() and in a() && b(), the call to a() occurs before the call to b().
In simple cases, if a() returns true, then in the expression a() || b() the call to b() will not be executed, because it won't affect the result. Similarly, if a() returns false, then in the expression a() && b(), the call to b() will not be executed.
In the code in the example, the increments to b and c won't be performed, because ++a produces a non-zero value, so the result of the expression is true without needing to evaluate anything after ++a.
Operator precedence has nothing to do with order of evaluation. Precedence is the priority for grouping different types of operators with their operands.
So, the expression
++a || ++b && ++c;
will be evaluated as
++a || (++b && ++c);
Logical AND and Logical OR operator constitute sequence points and therefore guarantee a particular order of evaluation for their operands which is left to right.
Order of evaluation:
Ordering
......
If a sequence point is present between the subexpressions E1 and E2,
then both value computation and side effects of E1 are
sequenced-before every value computation and side effect of E2
Rules
.....
2) There is a sequence point after evaluation of the first (left) operand and before evaluation of the second (right) operand of the following binary operators: && (logical AND), || (logical OR), and , (comma).
Logical OR operation (expr1 || expr2) employs short-circuiting behavior. That is, expr2 is not evaluated if expr1 is logical 1 (true).
The initial value of a, b and c is 0. In the expression:
++a || ++b && ++c;
++a -> pre-increment a.
That means, the value of the expression ++a is resulting incremented value of a which will be 1. Since, || operator employs short-circuit behavior, the right hand side expression of || will not be evaluated. Hence, you are getting output - 1 0 0.
For better understanding, just try to change the ++a -> a++ in the expression.
The post increment operator also increase the value of operand by 1 but the value of the expression is the operand's original value prior to the increment operation. So, a++ will be evaluated to 0 and because of short-circuit behavior the right hand side expression of || operator (++b && ++c) will be evaluated.
The logical AND operation (expr1 && expr2) also employs short-circuiting behavior. With logical short-circuiting, the second operand, expr2, is evaluated only when the result is not fully determined by the first operand, expr1. That is, expr2 will be evaluated only if expr1 is logical 1 (true) and ++b will result in 1. So, if you do
a++ || ++b && ++c;
^^^
The output would be - 1 1 1.

Output of the following C program

What should be the output of this C program?
#include<stdio.h>
int main(){
int x,y,z;
x=y=z=1;
z = ++x || ++y && ++z;
printf("x=%d y=%d z=%d\n",x,y,z);
return 0;
}
The given output is :
x=2 y=1 z=1
I understand the output for x, but fail to see how y and z values don't get incremented.
This is a result of short-circuit evaluation.
The expression ++x evaluates to 2, and the compiler knows that 2 || anything always evaluates to 1 ("true") no matter what anything is. Therefore it does not proceed to evaluate anything and the values of y and z do not change.
If you try with
x=-1;
y=z=1;
You will see that y and z will be incremented, because the compiler has to evaluate the right hand side of the OR to determine the result of the expression.
Edit: asaerl answered your follow-up question in the comments first so I 'll just expand on his correct answer a little.
Operator precedence determines how the parts that make up an expression bind together. Because AND has higher precedence than OR, the compiler knows that you wrote
++x || (++y && ++z)
instead of
(++x || ++y) && ++z
This leaves it tasked to do an OR between ++x and ++y && ++z. At this point it would normally be free to select if it would "prefer" to evaluate one or the other expression first -- as per the standard -- and you would not normally be able to depend on the specific order. This order has nothing to do with operator precedence.
However, specifically for || and && the standard demands that evaluation will always proceed from left to right so that short-circuiting can work and developers can depend on the rhs expression not being evaluated if the result of evaluating the lhs tells.
In C, any thing other than 0 is treated as true, And the evaluation for the || start from left to right.
Hence the compiler will check first left operand and if it is true then the compiler will not check other operands.
ex. A || B - In this case if A is true then compiler will return true only, and will not check whether B is true or False. But if A is false then it will check B and return accordingly means if B is true then will return true or if B is false then it will return false.
In your program compiler first will check ++x(i.e 2) and anything other than 0 is true in C. Hence it will not check/increment other expressions.

I am wondering why this code would produce 2

I don't know if anyone could kindly explain this code for me?
unsigned int x = 0;
(x ^= x ) || x++ || ++x || x++;
printf("%d\n", x);
when I compile this on my computer using gcc 4.2, the output is 2.
Originally i thought maybe this behavior is unspecified but then i figure || will have lower precedence over other operators, so shouldn't the answer be 3? Since there are three "++".
Can someone explain? Thanks
(x ^= x) is evaluated and it yields 0, therefore:
(x++) is evaluated and it yields 0, therefore:
(++x) is evaluated and it yields 2, therefore it stops
It all boils down to one rule: || only evaluates its right side if its left side is false.
The issue is that the || operator is short-circuiting. As soon as it finds a true value, it no longer needs to check the remaining || statements; the answer is already known.
(x ^= x) evaluates to 0.
x++ evaluates to 0, then increments x to 1.
++x evaluates to 2 -- true.
The final or statement does not need to be computed. It "short-circuits" and immediately returns true.
The behaviour is well-defined. You are observing the short-circuiting behaviour of ||; the final x++ is never evaluated.
That is short-circuit semantics in action. The first expression x ^= x evaluates to 0, the second evaluates to 0 as well. The third one evaluates to 2, and then the logical expression is short-circuited since its result its already determined to be true.
Of course you shouldn't use such constructs, but let us analyze the expression.
There are 4 expressions combined with shortcut-OR:
a || b || c || d
b, c and d are only evaluated, if a is false, c and d only if b is false too, and d only if all from the before are false.
Ints are evaluated as 0 == false, everything else is not false.
x ^= 0
with x being 0 is 0 again.
x++
is evaluated and later increased, so it evaluates to 0, which invokes expression c, but later x will be increased.
++x
is first incremented, leading to 1, and then evaluated (leading to 1) which is the reason, why d is not evaluated, but the increment of b is pending, so we get 2.
But I'm not sure, whether such behaviour is exactly defined and leads to the same result on all compilers.
Avoid it.
The expressions between the || operators will be evaluated left to right until one is true:
(x ^= x )
Sets all bits in x to 0/off. (false);
x++
Increments x, it's now 1, but still false because this was a post increment.
++x
(pre-)Increments x, which is now 2 and also true, so there is no need for the right hand side of || to be evaluated.

Problem with operator precedence [duplicate]

This question already has answers here:
Why does "++x || ++y && ++z" calculate "++x" first, even though operator "&&" has higher precedence than "||"
(11 answers)
Closed 4 years ago.
The O/p comes out to be x=2,y=1,z=1 which doesnt agree with the operator precedence. I was running this on Turbo c++ compiler:
void main()
{
int x,y,z,q;
x=y=z=1;
q=++x || ++y && ++z;
printf("x=%d y=%d z=%d",x,y,z);
}
Actually the result is in complete accordance with standard C. The logical or operator (||) short circuits after ++x because it evaluates to a non-zero number, so the rest of them are ignored.
So starting at x=1, y=1, z=1, after the short circuit, you get x=2, y=1, z=1.
Operator precedence does not in any way determine the order in which the operators are executed. Operator precedence only defines the grouping between operators and their operands. In your case, operator precedence says that the expression
q = ++x || ++y && ++z
is grouped as
q = ((++x) || ((++y) && (++z)))
The rest has absolutely nothing to do with operator precedence at all.
The rest is determined by the semantics of each specific operator. The top-level operator in this case is ||. The specific property of || operator is that it always evaluates its left-hand side first. And if the left-hand size turns out to be non-zero, then it does not even attempt to evaluate the right-hand side.
This is exactly what happens in your case. The left-hand side is ++x and it evaluates to a non-zero value. This means that your whole expression with the given initial values is functionally equivalent to a mere
q = (++x != 0)
The right-hand side of || operator is not even touched.
x=y=z=1;
Makes all the variables = 1
q=++x || ++y && ++z;
Since ++x makes it = 2 and since it is not zero it stops checking the other conditions because the first one is true.
Thus, x=2, and y and z = 1
Logical && (AND) and || (OR) operators are subject to Short-Circuit.
"Logical operators guarantee evaluation of their operands from left to right. However, they evaluate the smallest number of operands needed to determine the result of the expression. This is called "short-circuit" evaluation."
Thus, for logical operators always evaluated as (no matter || or &&) left to right.
And as previously mentioned, precedence here only determines who takes who.
Then left to right rule;
q = ++x || ++y && ++z;
//ok, lets play by rule, lets see who takes who:
//first pass ++ is badass here (has highest precedence)
//q = (++x) || (++y) && (++z)
//second pass &&'s turn
//q = (++x) || ((++y) && (++z))
//done, let's do left to right evaluation
q = (++x) || rest..
q = (true)|| whatever..
hope that helps more clear.

Resources