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.
Related
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.
#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.
This question already has an answer here:
Logical AND, OR: Is left-to-right evaluation guaranteed?
(1 answer)
Closed 9 years ago.
Is the left part of the && always evaluated before the right part?
I want to know because I'm wondering if I can change
if(i > 0)
if(someFunc(arr[i-1], arr[i]))
//do work
to
if(i > 0 && someFunc(arr[i-1], arr[i]))
or would this cause undefined behaviour if the right side gets evaluated first and arr[0-1]is referenced?
Yes, because of short-circuit behavior of logical && operator, in case of && second expression evaluates only when first is true. Read following:
6.5.13 Logical AND operator
4 Unlike the bitwise binary & operator, the && operator guarantees left-to-right evaluation;
there is a sequence point after the evaluation of the first operand. If the first operand
compares equal to 0, the second operand is not evaluated.
From Is short-circuiting boolean operators mandated in C/C++? And evaluation order?
So if i > 0 is false (for example if i = 0) then result of i > 0 expression will be false, and then second operand someFunc(arr[i-1], arr[i] will not be called (evaluated).
Accordingly, if(i > 0 && someFunc(arr[i-1], arr[i])) is safe to code, but be-careful i - 1 shouldn't be > max index value of arr[]. Really I will prefer this form of if compare to nested if blocks (flat is better then nested).
From #Maroun Maroun's answer "Is there any reason for asking if(1 || Foo())?" Additional information that might help you:
if(a && b) - if a is false, b won't be checked.
if(a && b) - if a is true, b will be checked, because if it's false, the expression will be false.
if(a || b) - if a is true, b won't be checked, because this is true anyway.
if(a || b) - if a is false, b will be checked, because if b is true then it'll be true.
Yes. Order of evaluation for the operators &&, ||, , and ? :(ternary operator) are guaranteed from left to right. A sequence point occurs between the left and right sub-expression of these operands. All the side effects of the left sub-expression of these operators (&&, || and ,) are completed before any access to its right sub-expression.
would this cause undefined behavior if the right side gets evaluated first and arr[0-1] is referenced?
Yes. If that were the case, it would cause undefined behavior. (But it doesn't happen that way, so there won't be any undefined behavior.)
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.)
The following code snippet:
int i=-3,j=2,k=0,m;
m=++i && ++j || ++k;
can be evaluated using two concepts,I believe:
1.Since ++ operator has greater precedence than the logical operators,so first all increment operators will be evaluted,then && having higher precedence than || will be computed.In this process,k will be incremented.
2.First && operator will be evaluated.For this ++ i and ++j will be computed.Since the result of the && operator is 1,no need to evaluate the ++k.So k will not be incremented.
When I try it on a system, the result proves reasoning 2 to be correct and 1 to be wrong. Why is it so?
Oli is right... You're confusing precedence with evaluation order.
Precedence means that the expression is interpreted as:
m = ((((++i) && (++j)) || (++k));
As opposed to, say:
m = (++(i && ++(j || (++k)))
Precedence doesn't change the fact that the LHS of the || operator will always be evaluated before the RHS.
In attempting to be efficient, evaluation of an OR statement (executed from left to right) stops when the LHS is true. There is no need to start evaluating the RHS - there is no concept of "precedence" except within the same group of an expression (when it matters to the value of the expression whether you first do A or B. Example: 5 + 3 * 2 should evaluate to 11. But in evaluating ( 5 + 6 > 3 * 2) it doesn't matter whether you do the addition before the multiplication - it doesn't change the result of the comparison. And in practice this gets evaluated left-to-right. Thus you get the result you observed.
See also this earlier answer
The && and || operators force left-to-right evaluation. So i++ is evaluated first. If the result of the expression is not 0, then the expression j++ is evaluated. If the result of i++ && j++ is not 1, then k++ is evaluated.
The && and || operators both introduce sequence points, so the side effects of the ++ operators are applied before the next expression is evaluated. Note that this is not true in general; in most circumstances, the order in which expressions are evaluated and the order in which side effects are applied is unspecified.