In which order is && and || is evaluated in C? - c

if (2<3 || 3<4 && 5>6) printf("OK");
else printf("FAIL");
I am confused on how will the computer evaluate this if statement. My guess is (Since && comes before ||):
if ((2<3 || 3<4) && 5>6) printf("OK");
else printf("FAIL");
Since the statement is wrong the if should print FAIL. But the answer sheet says that the answer is OK.
My question is that when encountered with a situation like this should i evaluate from left to right or start from &&?

Test yourself. C does not evaluate all expressions when the result is known
https://godbolt.org/z/dE4y3M , https://godbolt.org/z/E_sxhX
#include <stdio.h>
int first(int x)
{
printf("FIRST\n");
return x;
}
int second(int x)
{
printf("SECOND\n");
return x;
}
int third(int x)
{
printf("third\n");
return x;
}
int fourth(int x)
{
printf("fourth\n");
return x;
}
int main()
{
if(first(0) || second(0) && third(1) || fourth(1)) printf("TRUE\n");
else printf("FALSE\n");
}

Logical and (&&) is higher than logical or (||), and is evaluated left to right.
See this.
if (2<3 || 3<4 && 5>6) printf("OK");
else printf("FAIL");
Is the same as...
if ((2<3) || ((3<4) && (5>6))) printf("OK");
else printf("FAIL");

If you check the operator precedence table, you'll see that && has higher precedence than ||. It also shows that < and > have higher precedence than both of them.
This means that this expression:
if (2<3 || 3<4 && 5>6)
Will be parsed as:
if ((2<3) || ((3<4) && (5>6)))
So the operands of the highest precedence operators are grouped first followed by the next highest. When dealing the operators of equal precedence, some group left-to-right while others group right-to-left.
It's good practice however to always use parenthesis around these operators to make it clear to the reader what your intentions are.

The logical AND operator has a higher priority than the logical OR operator. So the expression in the if statement
if (2<3 || 3<4 && 5>6) printf("OK");
is equivalent to the following expression
if ( 2<3 || ( 3<4 && 5>6 ) ) printf("OK");
The both operators are evaluated left-to-right.
And for the logical OR operator "If the first operand compares unequal to 0, the second operand is not evaluated." (C Standard)
So as the first operand of the logical OR operator 2 < 3 yields true then the result of the whole expression is not equal to 0 and evaluates as true (its value is the integer 1).

Related

Confusion about operator precedence in C

I got bit confused by how to interpret the precedence of operators in the following snippet:
int a,b,c,d;
a=b=c=d=1;
a=++b>1 || ++c>1 && ++d>1
The values of a,b,c,d at the end of this code snippet are 1,2,1,1 respectively.
I was trying to decipher what was happening here but to no avail.
I know the precedence of ++ is higher than any other operators so why b,c, and d doesn't equal 2?
According to the result I received, I guess that the expression was evaluated left to right when at the first step b is incremented to 2 therefore ++b>1 is true then because there is a logical OR the answer is returned immediately.
Like if it was : (++b>1) || (++c>1 && ++d>1)
Does operator precedence have any other role other than to group operands together? What does it have to do with the order of execution for example?
The reason is because of Short-circuit evaluation which means that the evaluation will stop as soon as one condition is evaluated true (counting from the left).
This:
a=++b>1 || ++c>1 && ++d>1
is therefore similar to this:
if(++b > 1) {
a = true;
} else if(++c > 1) {
if(++d > 1) {
a = true;
}
}

Short circuit evaluation with both && || operator

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);
}

Precedence of && over || [duplicate]

This question already has answers here:
Evaluation of the following expression
(3 answers)
Closed 3 years ago.
As I know logical operator && has higher precedence than ||. On running the code:
#include <stdio.h>
int main()
{
int i = 1, j =1, k = 1;
printf("%d\n",++i || ++j && ++k);
printf("%d %d %d",i,j,k);
return 0;
}
is giving the output:
1
2 1 1
which is possible only when ++i || ++j && ++k is evaluated like this:
(++i) || (++j && ++k)
But, according to operator precedence rule it should be evaluated as:
(++i || ++j) && (++k)
and hence output should be:
1
2 1 2
What is going wrong with this?
NOTE: As per my understanding I think an operator of higher precedence evaluated as follows(if it is left associative):
1. Evaluate its left expression
2. Then evaluate its right expression(if needed)
Am I wrong?
The || operator short-circuits - if its first operand evaluates to true (nonzero), it doesn't evaluate its second operand.
This is also true for &&, it doesn't use its second operand if the first one is false. This is an optimization that's possible because any boolean value OR true is true, and similarly, any boolean value AND false is always false.
OK, so you're confusing precedence with evaluation order. Nothing is contradictional here at all:
++i || ++j && ++k
is grouped as
(++i) || (++j && ++k)
since && has higher precedence. But then the LHS of the OR operation is true, so the whole RHS with its AND operation is discarded, it isn't evaluated.
To your note in the edit: yes, you're wrong: operator precedence is still not the same as order of evaluation. It's just grouping.
You say:
which is possible only when ++i || ++j && ++k is evaluated like this:
(++i) || (++j && ++k)
But, according to operator precedence rule it should be evaluated as:
(++i || ++j) && (++k)
The first grouping is correct because the precedence of && is higher than the precedence of ||. Then the expression as a whole evaluates the LHS of the ||, with the side-effect of incrementing i, which evaluates to true. That means that the RHS of the || (the && expression) is not evaluated at all because it is not needed to determine the truth of the overall expression.
So, the compiler is correct; you misunderstood precedence in some way.
Why is the first grouping correct? According to first grouping || has higher precedence than &&. What is going wrong with me?
You don't understand precedence, it seems, or you don't understand the interaction of precedence with order of evaluation. The first grouping gives higher precedence to &&.
If you have a + b * c, where * has a higher precedence than +, then it is evaluated as a + (b * c), is it not? Change + to || and * to && and the expressions are isomorphic and the interpretation is similar.
The big difference between the arithmetic expression and the logical expression is that the operands of the logical expression have to be evaluated left-to-right but the operands of the arithmetic expression do not; the compiler could evaluate b * c before evaluating a (but must evaluate b * c before doing the addition). By contrast, in the logical expression (a || b && c), the compiler must evaluate a before evaluating b && c, and when a turns out to be true, it must not evaluate either b or c, let alone b && c.
Firstly, as you said it yourself, && has higher precedence, which means that operand grouping should be
(++i) || (++j && ++k)
Why you are saying that "according to operator precedence" it should be (++i || ++j) && (++k) is not clear to me. That just contradicts what you said yourself.
Secondly, operator precedence has absolutely nothing to do with order of evaluation. Operator precedence dictates the grouping between operators and their operands (i.e. operator precedence says which operand belongs to which operator).
Meanwhile, order of evaluation is a completely different story. It either remains undefined or defined by completely different set of rules. In case of || and && operators the order of evaluation is indeed defined as left-to-right (with mandatory early completion whenever possible).
So, operator precedence rules tell you that the grouping should be
(++i) || ((++j) && (++k))
Now, order-of-evaluation rules tell you that first we evaluate ++i, then (if necessary) we evaluate ++j, then (if necessary) we evaluate ++k, then we evaluate && and finally we evaluate ||.
Since you are misunderstanding precedence, let's try to clear it up with a mathematical example. Multiplication and division have a higher precedence than addition and subtraction. Which means that this expression:
a + b * c - d / e
Can be written like this:
a + (b * c) - (d / e)
Since you correctly stated that && has higher precedence than ||, this expression:
i || j && k
can be written like this:
i || (j && k)
You can think of it as "the operation with the highest precedence gets parenthesized first", if that helps.
(But precedence is different from evaluation - if i is true, then (j && k) will never 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.

Please explain an apparent conflict between precedence of && and || and the actual result of an expression [duplicate]

This question already has answers here:
Precedence of && over || [duplicate]
(4 answers)
Closed 8 years ago.
I don't understand the output of the following program:
#include<stdio.h>
int main()
{
int i=-3, j=2, k=0, m;
m = ++i || ++j && ++k;
printf("%d %d %d %d\n", i, j, k, m);
return 0;
}
The output is -2 2 0 1 instead of -2 3 1 1, implying that ++i was evaluated (and caused the || operator to short-circuit its right hand side) before the expression ++j && ++k which appears to contradict the fact that the && operator has higher precedence than ||.
Would someone explain why?
The output should be something like:
Error, line 2: 'm': undefined variable.
Edit: with that fixed, only the ++i should be evaluated. Precedence does not determine (or even affect) order of evaluation. Precedence means the expression is equivalent to ++i || (++j && ++k). Order of evaluation for || or && is always that the left operand is evaluated, then there's a sequence point. After the sequence point, the right operand is evaluated if and only if necessary to determine the final result (i.e., the right operand of || is evaluated if the left operand evaluated to zero; the right operand of && is evaluated if the left operand evaluated to non-zero).
In this expression, ++i is evaluated, then because it's the left operand of || and evaluated non-zero, none of the rest of the expression is evaluated.
-2 2 0 1
Lazy.
#include <stdio.h>
int main()
{
int i=-3,j=2,k=0;
int m=++i||++j&&++k;
printf("%d %d %d %d",i,j,k,m);
}
Compile, run and see for youself.
gcc tmp.c -o tmp
The expression:
++i || ++j && ++k
Is equivalent to:
(++i) || ((++j) && (++k))
Explaining:
++i is evaluated -- (-2) || ((++j) && (++k));
The || operator is evaluated -- (1);
Since 1 || anything evalutes true, the right operand is not evaluated. Thus, the && precedence doesn't matter here. This short circuiting is guaranteed in both C and C++ by the relevant standards (see Is short-circuiting logical operators mandated? And evaluation order?).
Now, try using a sub-expression, like this:
(++i || ++j) && ++k
Which is equivalent to:
((++i) || (++j)) && (++k)
Explaining:
++i is evaluated -- ((-2) || (++j)) && (++k);
|| is evaluated -- (1) && (++k)
++k is evaluated -- (1) && (1);
Evaluates true;
By way of explanation:
#include <stdio.h>
int main()
{
if (-1)
printf ("-1!\n");
else
printf ("Not -1.\n");
return 0;
}
Negative numbers are not false in C. Always compare boolean values to 0 (or FALSE) or you can get bitten by if (worked == TRUE) giving false negatives.

Resources