Does relational operator affect assignment operator operations? - c

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.

Related

What is the order of evaluation of the statements in this code?

I came across this question.
#include <stdio.h>
int main()
{
int k=8;
int x=0==1||k++;
printf("%d %d",x,k);
return 0;
}
The output is 1 9.
As this answer suggests that
Unlike the bitwise | 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.
I am unable to understand how the statement int x=0==1||k++ is evaluated,due to which the value of x and k becomes 1,9 respectively.
Can someone explain how such statements are evaluated by the compiler in c ?
"Unlike the bitwise | 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."
yes it's true ...
to make it clear first make sure that you are aware of these basics
1) (1 || any_var) is 1
2) Operator precedence is as follows
++
then
==
then
||
NOW coming to your doubt of || vs |
note that | (single pipe) operator ..,will execute both LHS and RHS , no matter what)
whereas
|| (double pipe) evaluates LHS of || first and if it is 1 it need not evaluate RHS (for speed)
RHS of || operator will not be evaluted if LHS comes out to be true.
but here 0==1 is false i.e 0==1 returns 0
hence RHS will be evalauted
so the statement
k++ is executed
but 8 is used (as property of post increment operator says--> first use then increment)
so 0||8 is definitely true (1) so x evaluates to 1
and then k is incremented after sequence point ie k is made equal to 9
hence output x=1 and k=9
I hope it clears your doubt :)
The Operator || (OR) evaluates to true in the cases:
ex: A || B
A is true,
B is true,
Both are true
Because this operation uses Short-Circuit Evaluation if A is evaluated to true, it means that the statement is true already and it won't evaluate B.
In your case 0==1 (0 equals 1) is clearly false, so it will evaluate k++. k++ is a tricky one (in my opinion). In the world of C true/false evaluation is based on being 0 or not (except for the times false means less than 0...) but in true/false evaluation 0 is false, everything else is true.
K++ means evaluate K then increment, so, if K is 0 it will be false and become 1, if it is anything else, it will be true and then increment.
In your case k == 8 so the result of k++ is TRUE and k will become 9. K being true means x evaluation resulted in TRUE (it was FALSE OR TRUE).
So the output is 1(True) 9(8++)
x is 1 because the expression: 0==1||k++ turns out to be true (which is 1 in C land). Why you ask? There are two sequence points here: 0 == 1 and k++. Since the first sequence point evaluates to false (0 in C land), the second sequence point is evaluated (because the short circuit operator is ||). The second sequence returns true (or 1). So, you the entire expression breaks down to: 0 || 1. Hence x is 1.
k is 9 because of k++;
HTH.

Explanation for this function's output

I am doing review questions which ask me "What is the output of the following," and I am having some trouble understanding something about this function:
int a = 1, b = 1, c = -1;
c = --a && b++;
printf("%d %d %d", a, b, c);
The output is 010. My question is about line 2, c = --a && b++. How is this line processed, and how does it work/change the values? And if it were c = --a || b++? From my understanding I thought the output would be 020.
The key concept to understanding the result is short-circuit evaluation of Boolean operators (&& and ||) -- if, after evaluating the left-hand side of a Boolean operator, the value of the right-hand side cannot affect the overall result, then it will not be evaluated and any side-effects it would produce will not happen.
In the first case, since --a evaluates to 0 (=false) the second part of ... && ... is not evaluated, since "false AND anything" will always be false. Specifically, b++ is never executed, and so its value remains 1 in the output.
In the case of --a || b++, the value of the whole expression cannot be determined by the left-hand side ("false OR something" can still be true) so the b++ is evaluated (and it's side-effect, incrementing b, happens).
The other concept needed to fully understand the results is the difference between pre- and post-increment/decrement operators. If the -- or ++ appears before the variable (as in --a) then the variable is decremented or incremented first and new value is used to evaluate the whole expression. If the -- or ++ appears after the variable (as in b++) then the current value of the variable is used to evaluate the expression and the increment/decrement happens after this has happened.
It should be noted that expressions that try to combine two or more instances of --/++ of the same variable (e.g. a++ + ++a) are quite likely to invoke undefined behaviour -- the result may vary by platform, compiler, compiler and even the time of day.
In the expression c = --a && b++, a gets decreased and returned. Now the second argument of the expression --a && b++ is not evaluated because of short circuit evaluation---once we see that --a==0 we already know that the expression will be 0 regardless of what is the other argument---, so b remains unchanged.
Decreased a is 0 and b remains 1.
The output is, as you suggest, 0 1 0.
Regarding the second question, if you write c = --a || b++, the variable a again goes to zero but the expression can still evaluate to true---we must thus evaluate the second part as well, thus executing b++ which returns 1 and increases b. In this case the output would be 0 2 1, because c is assigned the value of 0 || 1 which is 1.
In short, read up on
pre- and post-increment in C and C++ and on
short circuit evaluation.
The thing you need to focus on here first is the properties of prefix and postfix operators and their differences.
For Postfix increment and decrement operators, C11, chapter §6.5.2.4, (emphasis mine)
The result of the postfix ++ operator is the value of the operand. As a side effect, the
value of the operand object is incremented [...] The postfix -- operator is analogous to the postfix ++ operator, except that the value of
the operand is decremented.
For Prefix increment and decrement operators, C11, chapter §6.5.3.1, (emphasis mine)
The value of the operand of the prefix ++ operator is incremented. The result is the new
value of the operand after incrementation. [...] The prefix -- operator is analogous to the prefix ++ operator, except that the value of the
operand is decremented.
Now, there comes the property of the Logical AND (&&) operator. From chapter §6.5.13, (again, emphasis mine)
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 your case,
int a = 1, b = 1, c = -1;
c = --a && b++;
gets evaluated as
c = 0 && .....; // done..., a is decremented to 0,
// so, LHS of && is 0, RHS is not evaluated,
// b remains 1
// and finally, C gets 0.
On the other hand, if logical OR (||) would have been used, then, as per the property, mentioned in chapter §6.5.14
[...] 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.
So, for the case
int a = 1, b = 1, c = -1;
c = --a || b++;
it will be evaluated as
c = 0 || 1; //yes, b's value will be used, and then incremented.
So,
printf("%d %d %d", a, b, c);
will be
0 2 1
b++ is simply never executed because --a evaluates to false in an and condition.
The right side of the and is never executed because not needed. Hence b is never incremented and hence the output you did not expect.
c = --a && b++;
In this first --a is evaulated and a becomes 0 , as soon as 1 operand of && is false , b++ is not evaluated , therefore ,b remains 1 and c becomes 0.
The line :
c = --a && b++;
decreases a to 0, so the statement 0 && anything else results to 0. This is why a and c result to 0, as it seems you have understood.
Now let's see the part you don't get. When a is evaluated to 0, the right part of && does not need to be evaluated, as no matter what the value of the right part will be calculated to be, the result will be 0. This means that b++ will not be evaluated and therefore b will retain its initial value. This is why you see the value 1 instead of 2, and consequently the output 0 1 0 instead of 0 2 0.
--a : mean you decrease a before do the line. b++: increase b after do the line. so that c ( at that time ) = 0+1 =1; then: a =0, b = 2, c =1; OK

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.)

Evaluation of the following expression

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.

Require explanation for the output

Code:
#include<stdio.h>
int main()
{
int j = 7, i = 4;
j = j || ++i && printf("you can");
printf("%d %d",i,j);
return 0;
}
Output:
4 1
[Code Link][1]
The precedence of prefix operator is higher than logical operators.
2.Logical && has higher precedence than logical ||.
In Logical AND(&&) if first operand evaluates to false than second will not be evaluated and In Logical OR(||) if first operand evaluates to true, then second will not be evaluated.
The complete expression is evaluating to true, therefore j is 1 .
Doubts:
Why the first rule is not followed here? Shouldn't it be correct?
j=(j||((++i) &&printf("you can")));
Therefore value of i becomes 5, in the printf statement.
Why are the general precedence rules are violated here? Associativity comes into action when precedence of two operators is same. Shouldn't the compiler first see whether to evaluate || or &&?
If || is evaluated first, which shouldn't be as per my knowledge, then result is correct. However, if it is not evaluated first, then you can51 should be printed.
In this expression:
j = j || ++i && printf("you can");
There's a sequence point after the || and it is evaluated from left to right. Since j is non-zero, the rest of the expression is not evaluated. Hence, j || (....) becomes true which is 1. Since is ++i is not evaluated i remains 4. Hence, the output is 4, 1.
From the C standard:
Annex C
— The end of the first operand of the following operators: logical AND
&& (6.5.13); logical OR || (6.5.14); conditional ? (6.5.15); comma ,
(6.5.17).
If you j was zero then ++i && printf("you can") would have been evaluated and i would become 5 and you can will also be printed. You are correct about the precedence of ++ being greater than ||, but since there's a sequence point, j|| is evalauted first.
j || ++i && printf("you can") evaluates to true, which is represented by 1. Because it is an OR, and because j is non-zero, only the left hand of the OR is evaluated, so the ++i and the printf aren't evaluated. Thus j is 1 and i stays at 4.
Of course, real code should never every do anything like that. You should always write code in ways that the order of operations is obvious, and you should almost never have code with side effects in OR statements.
What you have here:
j = j || ++i && printf("you can");
Is a logic expression (there's no math happening). Let's break it down:
++i // as a mathematical expression this is i=i+1 (5 in your case)
printf("you can"); // printf returns the number of chars written, (7)
So you'd expect this to be:
j = 7 || 5 && 7;
The output of the above expression is simply 1. So even if this executed you should see j=1. So why don't you see the printf() output?
The reason to that is that whole expression didn't run. It doesn't have to. Consider:
result = TRUE || (anything else);
Anything that's "true" or'd with anything else will always return true. The compiler knows this and once it sees 7 || it equates that to true || and says "I know enough, set j to true and move on".
This is why the expression doesn't increment i and why it doesn't print "you can".
Now if you were to flip the expression:
j = ++i && printf("you can") || j;
The logic stays the same but the compiler doesn't see the || until it's evaluated everything else, so i will be incremented and the printf will be displayed.
I ran this program two ways:
j = j || ++i && printf("you can");
then, like this:
j = j || (++i && printf("you can"));
The output for both was 4 1. Before I ran them, I expected to get the exact same result from both due to the left to right associativity of logical or. The entire expression is gonna be evaluated from left to right regardless. The role of the parentheses is to ensure that an expression is evaluated as one expression, and doesn't necessarily mean that it will be the first expression to be evaluated. If you want more evidence of this, try something simple:
j = 1 || (++i);
Even though (++i) is in parenthesis, it is never evaluated. Again, because of left to right associativity.

Resources