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.
Related
I am working on a simple C program, but ran in to some confusion. Below is the code:
int main(void) {
int i, j, k;
i = 3;
j = 4;
k = 5;
printf("%d ", i < j || ++j < k);
printf("\n"); // LINE 1
printf("%d %d %d", i, j, k); // LINE 2
return 0;
}
In the above program, the variable j starts off being 4. Then in the printf statement of line 1 we increment the value of j by 1(++j = 5).
So theoretically, I would assume that when j is printed in printf(line 2) it prints as 5, since we did an incrementation in line 1 for j. However, every time I run the code, line 2 prints the original value of j which was 4, and NOT 5.
Is there something I am missing?
j is never incremented because ++j is never evaluated. The OR operator is satisfied when it first checks i < j.
This is an example of short-circuiting evaluation. When a boolean expression is A || B, if A is true, there is no need to evaluate B, and most languages adhere to that.
In this case, i < j is true, so the ++j < k is ignored.
This is a good example to learn "what is short-circuit evaluation". In the boolean expression (i < j || ++j < k) that you used above; || is the short-circuit OR.
So, to get the result as TRUE in the boolean expression one being true of one condition is enough. When considering i
In brief the difference between | and || is | consider the both conditions whether the first one is true. But || nevwr consider or process the second condition if the first condition is true and it jumps to the next line.
Looking at this expression:
i < j || ++j < k
The preincrement operator ++ has the highest precedence followed by the less-than operator < followed by the logical OR operator ||. So it parses like this:
(i < j) || ((++j) < k)
The logical OR operator || evaluates to true (specifically the value 1) if either the left side or the right side evaluates to true. Because of this, it also has the property that the right side will not be evaluated if the left side evaluates to true, since the result of the whole expression is already known at that point. This is commonly referred to as short-circuit evaluation.
This behavior is dictated by section 6.5.14p3 of the C standard regarding the logical OR operator:
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.
Going back to the expression, i < j is evaluated first. The value of i is 3 and the value of j is 4, so 3 < 4 evaluates to 1. Because this is the value of the left side of the || operator, the result of the || operator is 1 and the right side ++j < k is not evaluated, so j is never incremented.
This is called short-circuit evaluation. If i < j equates to true then ++j < k will not be evaluated.
This is a good example to learn "what is short-circuit evaluation". In the boolean expression (i < j || ++j < k) that you used above; || is the short-circuit OR.
So, to get the result as TRUE in the boolean expression one being true of one condition is enough. When considering i
In brief the difference between | and || is | consider the both conditions whether the first one is true. But || nevwr consider or process the second condition if the first condition is true and it jumps to the next line.
I am not getting expected output in the following C code
main(){
int i=0,j=-2,k=0,m;
if((!i||--j&&k++)&&(i++||j++&&!k++))
{
printf("i=%d j=%d k=%d",i,j,k);
}
return 0;
}
I got the output in compiler as :
i=1 j=-1 k=1
But I don't understand what exactly is going on here.
I think the if statement should not run since its argument is false
Note the first bracket (!i||--j&&k++)
here as !i=1 hence this bracket is true since anything with 1 under OR operator will be true.
out values become: i=0, j=-3, k=1
Now notice the second bracket: (i++||j++&&!k++)
Here we have ( 0 || -3 && !1) = 0, false
as the brackets are separated by &&, the whole argument of if statement becomes false.
Please explain me where my argument is wrong. I am a new to C
The logical AND operator && and the logical OR operator || are short circuit operators, meaning that the right side won't be evaluated if the result of the expression can be determined from the left side.
So when this subexpression runs:
(!i||--j&&k++)
Which is parsed as:
(!i||(--j&&k++))
The left side of the || evaluates to true, so --j&&k++ is not evaluated, meaning the value of j remains -2 and the value of k remains 0.
So the left side of the outermost && is true, so now we evaluate the right side:
(i++||j++&&!k++)
Which is parsed as:
(i++||(j++&&!k++))
i is incremented to 1, then the old value is used in ||. The old value of 0 evaluates to false so the right side is evaluated. j is incremented to -1 and the old value of -2 evaluates to true, so the right side of && is evaluated. k is incremented to 1 and the old value of 0 is applied to the ! operator which evaluates to true. This makes the entire expression true and the statement is printed, at which time i is 1, j is -1, and k is 1.
Let’s spread this out a little to make reading it easier:
int i = 0, j = -2, k=0, m;
(!i || --j && k++) && (i++ || j++ && !k++)
As you note !i is true (value 1), so the || is true. The || operator is defined not to evaluate its right operand if the left operand is true, so --j && k++ is not evaluated and has no effect. (The right operand is --j && k++ because && has higher precedence than ||, so A || B && C is structured as A || (B && C).)
That settles the left operand of the central &&. In the right operand, i++ increments i to 1 but evaluates to the current value of i, 0, so it is false for the purposes of the || operator. So the right operand of that || is evaluated.
That operand is j++ && !k++. Since j is −2, j++ changes j to −1 and evaluates to −2, which is a value of true for the purposes of &&. Then k++ increments k to 1 but evaluates to 0, and !k++ changes this to 1, yielding true for the && and therefore true for the previous || and the central &&.
At this point i is 1, j is −1, and k is 1, which is the result you got.
you may be missing that if statements ends once they are satisfied, so (!i||--j&&k++) is only going to compute i and the other operations are going to be disregarded. By that I mean j is going to be -2 by the end of the first statement.
why would the second line
int i=-3, j=2, k=0, m;
m = ++i && ++j || ++k;
terminate after ++j and ignore ++k ?
I know the first half make TRUE value and would return TRUE whatever the following value is. But what is the condition to stop executing following instrument? As long as we can confirm the final value?
&& has higher precedence than that of ||. ++i and ++j binds to it and
m = ++i && ++j || ++k;
is parsed as
m = (++i && ++j) || ++k;
Since both the sub-expressions ++i and ++j are non zero, it is interpreted as true. Due to short circuit behavior of logical operators second (right) sub-expression is not evaluated in case of || if left becomes true.
Note that the left sub-expression for || is (++i && ++j), not j++.
The condition is exactly that. In an OR in C, whenever the result is found to be true, none of the rest of expressions are even evaluated.
If you want to test true or false and also be sure that the variables involved are increased, you should instead increase the variables before and then test:
++i;
++j;
++k;
m = i && j || k;
The || operator does not evaluate the second operand if the first operand evaluates TRUE.
And the && operator does not evaluate the second operand if the first operand evaluates FALSE.
The operands of logical-AND and logical-OR expressions are evaluated from left to right. If the value of the first operand is sufficient to determine the result of the operation, the second operand is not evaluated. This is called "short-circuit evaluation." There is a sequence point after the first operand. See Sequence Points for more information.
Get the answer you want: here
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.
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.