Evaluation of the following expression - c

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.

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.

If ++ (pre/post) have higher precedence, why && is being evaluated first? [duplicate]

This question already has answers here:
Behaviour of && in C programming language
(5 answers)
Closed 9 years ago.
Here's my program:
int main(void)
{
int i, j, k, m;
i=-3, j=2, k=0;
m = k++ && ++i && ++j;
printf("%d, %d, %d, %d\n", i, j, k, m);
return 0;
}
The output of the program above is:
-3 2 1 0
But according to operator precedence table, ++ should have evaluated first I guess.
I also tried putting parenthesis around them, but still the output remains same.
I read somewhere that putting parenthesis around will make it evaluate first, no matter what.
Somebody, please make it clear, how it's evaluated.
Thanks in advance.
What's happening here is short-circuiting. k++ evaluates to 0, which is false. Thus the entire boolean expression k++ && ++i && ++j is false, so ++i and ++j are never executed.
You are confusing precedence with order of evaluation. Precedence defined how the operands are grouped. The higher precedence of ++ makes the expression equivalent to:
m = (k++) && (++i) && (++j);
But the evaluation order is irrelevant. The shortcut circuit of && guarantees
that its left-hand operand is evaluated first.
In general, most operator doesn't specify the order of evaluation, with four exceptions: logical AND &&, logical OR||, conditional operator ?: and comma operator ,.
As a concrete example of different order of evaluation:
Given int i = 0, the result of i + (i++) is unspecified, the compiler may evaluates i++ first, which modifies the value of i, the compiler may choose to evaluates i first. You should avoid expressions like these.
On the other hand, the result of i && (i++) is determined, as && ensures the left operand i is evaluated first, since it's zero, the right operand i++ is never evaluated.

Does relational operator affect assignment operator operations?

Why the output of below mentioned program is 0 not 20 ?
#include <stdio.h>
int main()
{
int i = 10, j = 0;
if (i || (j = i + 10))
/* do something */;
printf("%d\n",j);
}
Yes, the concept is called Short-Circuit (in logical &&, || operators expression).
In the case of any logical expression (includes ||, &&) compiler stop evaluation expression as soon as result evaluated (and save executions).
The technique for short-circuit is:
!0 || any_expression == 1, so any_expression not need to evaluate.
And because in your expression i is not zero but its 10, so you can think if consdition (i || (j = i + 10)) just as i.
Logical OR 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 unequal to 0, the second operand is not
evaluated.
Similarly for && (and operator):
0 && any_expression == 0, so any_expression not need to evaluate.
In your expression:
(i || (j = i + 10) )
------------
^
| Could evaluate if i is 0,
as i = 10 (!0 = true), so j remains unchanged as second operand is not evaluated
For or || operator answer can be either 0, 1. To save execution, evaluation stops as soon as results find. So if first operand is non-zero result will be 1 (as above) for the expression. So for first operand i = 10 compares unequal to 0, the second operand (j = i + 10) is not evaluated so j remains 0 hence output of your code is 0.
Note: Short-circuit behavior is not only in present in C but concept is common to many languages like Java, C++, Python. (but not all e.g. VB6).
In C short-circuiting of logical expressions is guaranteed has always been a feature of C. It was true when Dennis Ritchie designed and implemented the first version of C, still true in the 1989 C standard, and remains true in the C99 standard.
A related post: Is short-circuiting boolean operators mandated in C/C++? And evaluation order?
|| is a short-circuit operator - if the left hand side evaluates to true then the right hand side does not need to be evaluated. So, in your case, since i is true then the expression j = i + 10 is not evaluated. If you set i to 0 however then the right hand side will be evaluated,
In if (i || (j = i + 10)), there are two boolean expression to evaluate. The thing is, the first one is true, therefore there is no need to compute the second. It's purely ignored.
because || is a short-circuit operator (so is the && operator).
so in (i || j = i+10), i is 10, left part of || is true, the expression j = i+10 didn't happen, as a result, j=0.

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.

Resources