I tried the following code snippet:
void main()
{
int x = 1,y = 1,z = 1;
++x || ++y && ++z;
printf("x = %d\ny = %d\nz = %d\n",x,y,z);
}
The output I expected was:
x = 2
y = 2
z = 2
But I am getting the output:
x = 2
y = 1
z = 1
What is the reason for this?
This is because of short-circuiting.
http://en.wikipedia.org/wiki/Short-circuit_evaluation
When this is evaluated:
++x || ++y && ++z;
The first part ++x already determines the value of the entire expression. So the ++y && ++z is not executed at all. So the side-effects of ++y and ++z are not invoked.
The result of ++x is nonzero, so evaluates to true, so short-circuits the || operator. ++y && ++z is not executed.
The reason is you're using Brobdingnagian boolean expressions with side effects.
The operators && and || are "short-circuiting". That means if the result of the expression is determined after the left operand is evaluated, the right operand never gets evaluated.
Avoid using expression with side-effects as operands of boolean operators. Even if the behaviour is what you want.
Related
This question already has answers here:
Is short-circuiting logical operators mandated? And evaluation order?
(7 answers)
Closed 5 years ago.
#include <stdio.h>
main()
{
int x = 1, y = 0, z = 5;
int a = x && y || z++;
printf("%d", z);
}
This code gives me output : 6
#include <stdio.h>
main()
{
int x = 1, y = 0, z = 5;
int a = x && y && z++;
printf("%d", z);
}
This code gives me output : 5
Why the second program gives ouput as 5 even though z was incremented same like in first program?
The && operator (as well as the || operator) is a short-circuit operator. That means that if the left operand evaluates false, the result is false regardless of the right operand, so the right operand is not evaluated.
From section 6.5.13 of the C standard:
4 Unlike the bitwise binary & 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 equal to 0, the second operand is not evaluated.
So in the case of this expression:
x && y && z++;
x && y is evaluated first. Since x is 1, y is evaluated and found to be 0, so the result of the first && is 0. Now we have:
0 && z++
Since the left operand is 0, the right operand is not evaluated. This means that z is not incremented.
This is in contrast to expression in the first piece of code:
x && y || z++
As before, x && y evaluates to 0, leaving us with:
0 || z++
Since the left operand is 0, the right operand needs to be evaluated. This results in z getting incremented.
Evaluation of x && y && z++ stops after y because y==0. z++ is not executed.
The initializer in this declaration
int a = x && y || z++;
is equivalent to
int a = ( x && y ) || ( z++ );
According to the C Standard relative to the logical OR operator (6.5.14 Logical OR operator)
4 ... If the first operand compares unequal to 0, the second operand is
not evaluated.
However the first operand that is ( x && y ) compares equal to 0 (due to the variable y is equal to 0). So the second operand ( z++ ) is evaluated.
The initializer in this declaration
int a = x && y && z++;
is equivalent to
int a = ( x && y ) && ( z++ );
According to the C Standard relative to the logical AND operator (6.5.13 Logical AND operator)
4 ...If the first operand compares equal to 0, the second operand is
not evaluated
So as the first operand ( x && y ) compares equal to 0 then the second operand ( z++ ) is not evaluated.
I know what is short circuit evaluation in C.
a && b (operand b is not checked if a = 0)
a || b (operand b is not checked if a = non zero)
But I am stuck at this question
int x = 0;
if (5 || 2 && ++x)
printf("%d", x);
This outputs 0.
My first thinking goes as follows:
According to precedence table , precedence is ++, &&, || (descending order)
++x: evaluated.x becomes 1.
2 && ++x evaluated. Both operands are evaluated.
|| is evaluated.
But according to this, 1 should be printed, not 0.
My second thinking goes as this:
5 || anything
anything is not evaluated because of short circuit evaluation, so no precedence comes into play here.
The expression 5 || 2 && ++x is equivalent to 5 || (2 && ++x) due to operator precedence.
The run time evaluates the expression 5 || 2 && ++x from left to right.
As we know in OR if first condition is true it will not check the second condition.
So here 5 evaluated as true and so (2 && ++x) will not be performed.
That's why x will remain 0 here.
Correct. The expression is short circuited. You can test it with this.
if(5 || ++x) {
printf("%d\n",x);
}
Please explain output of this program.
#include<stdio.h>
int main()
{
int x=0;
x ^= x || x++ || ++x || x++;
printf("\n%d",x);
}
O/p is 3 (http://codepad.org/X49j0etz)
According to me output should be 2.
as || is a sequence point as far as i remember.
so expression becomes.
x ^= 0 || 0 || 2 || 2;
so after evaluation of this expression(x || x++ || ++x || x++;) x becomes 3
x = 3 ^ 1
so x becomes 2;
I'm pretty sure the answers claiming undefined behaviour are correct, but there is also a simple explanation for how you can arrive at the result of 3.
Just consider that the last x++ is never evaluated because the last || operation short-circuits, and let's assume that the side effects are applied before the ^= is evaluated. Then you are left with
x = 2 ^ 1;
Unsurprisingly resulting in 3.
This is an undefined behavior in c. Because we cannot predict in which direction the expression is evaluated
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
why "++x || ++y && ++z" calculate "++x" firstly ? however,Operator "&&" is higher than "||"
The following program does not seem to work as expected. '&&' is to have higher precendence than '||', so the actual output is confusing. Can anyone explain the o/p please?
#include <stdio.h>
int main(int argc, char *argv[])
{
int x;
int y;
int z;
x = y = z = 1;
x++ || ++y && z++;
printf("%d %d %d\n", x, y, z);
return 0;
}
The actual output is: 2 1 1
TIA.
Precedence and order of evaluation have no relation whatsoever.
&& having higher precedence than || means simply that the expression is interpreted as
x++ || (++y && z++);
Thus, the left-hand operand of || is evaluated first (required because there is a sequence point after it), and since it evaluates nonzero, the right-hand operand (++y && z++) is never evaluated.
The confusing line is parsed as if it were:
x++ || (++y && z++);
Then this is evaluated left-to-right. Since || is a short-circuit evaluator, once it evaluates the left side, it knows that the entire expression will evaluate to a true value, so it stops. Thus, x gets incremented and y and z are not touched.
The operator precedence rules mean the expression is treated as if it were written:
x++ || (++y && z++);
Since x++ is true, the RHS of the || expression is not evaluated at all - hence the result you see.
Why does this code always produce x=2?
unsigned int x = 0;
x++ || x++ || x++ || x++ || ........;
printf("%d\n",x);
the 1st x++ changes x to 1 and returns 0
the 2nd x++ changes x to 2 and returns 1
at which point the or short circuits, returns true, and leaves x at 2.
x++ || x++ || x++ || x++ || ........;
First x++ evaluates to 0 first for the conditional check, followed by an increment. So, first condition fails, but x gets incremented to 1.
Now the second x++ gets evaluated, which evaluates to 1 for the conditional check, and x gets incremented to 2. Since expression evaluates to 1 (true), there's no need to go further.
Because of short circuit in boolean expression evaluation and because || is a sequence point in C and C++.
|| short-circuits. Evaluated from left, when a true value is found (non-zero) it stops evaluating, since the expression now is true and never can be false again.
First x++ evaluates to 0 (since it's post-increment), second to 1 which is true, and presto, you're done!
When you're evaluating "a || b || c || d || e || ..." you can stop evaluating at the first non-zero value you find.
The first "x++" evaluates to 0, and increments x to 1, and evaluating the expression continues. The second x++ is evaluated to 1, increments x to 2, and at that point, you need not look at the rest of the OR statement to know that it's going to be true, so you stop.
Because logical OR short-circuits when a true is found.
So the first x++ returns 0 (false) because it is post-increment. (x = 1)
The second x++ returns 1 (true) - short-circuits. (x = 2)
Prints x = 2;
Because of early out evaluation of comparisons.
This is the equivalent of
0++ | 1++
The compiler quits comparing as soon as x==1, then it post increments, making x==2
Because the first "x++ || x++" evaluates to "true" (meaning it is non zero because "0 || 1" is true. Since they are all logical OR operators the rest of the OR operations are ignored.
Mike
The || operator evaluates the left-hand expression, and if it is 0 (false), then it will evaluate the right-hand expression. If the left hand side is not 0, then it will not evaluate the right hand side at all.
In the expression x++ || x++ || x++ || ..., the first x++ is evaluated; it evaluates to 0, and x is incremented to 1. The second x++ is evaluated; it evaluates to 1, and x is incremented to 2. Since the second x++ evaluated to a non-zero value, none of the remaining x++ expressions are evaluated.
trying replacing || with |.--
It is the short circuiting of logical operators.
It's the same reason when you do
if (returns_true() || returns_true()){ }
returns_true will only get called once.