I have a doubt in the program below.
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;
}
I get the output as -2 2 0 1.
In OR operation if 1st value is true then it won't evaluate the 2nd one so i = -2 and j =2.
Then comes the AND operation . It will check for both the value to be true.So if k = 1 then m = 1.
So the output should be -2 2 1 1. I run and check and got output as -2 2 0 1 but I could not understand how.
You used a short circuit or. Since ++i evaluates to -2, which is not 0, it short circuits and doesn't evaluate the rest of the expression. As a result, neither j or k get incremented.
Also note that the short circuit operators, || and &&, are left associative and that || is higher precedence than &&. As a result, the || gets evaluated first, and early outs if the left hand side evaluates to true, while && early outs if the left hand side evaluates to false.
EDIT: Fixed a mistake with explaining the precedence.
Nothing after the || is evaluated, since the result of the expression ++i is nonzero.
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.
This question already has answers here:
Short circuit behavior of logical expressions in C in this example
(1 answer)
Operator Precedence vs Order of Evaluation
(6 answers)
Closed 7 years ago.
In the program shown below, prefix should be evaluated first because it has higher precedence, But answer is -2, 2, 0, 1 and it is explained in book "as LHS of || is true RHS is not evaluated."
Why is it so? All the increments should performed first and then logical should be checked because of precedence.
#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;
}
Don't get confused with Precedence and Order of evaluation.
The order of evaluation of logical OR || is left to right.
So if left = true then left || right will never execute right. In your code exactly same happened.
As you know, any non zero value treated as true in C, hence, ++i or -2 is true. So,
m = ++i || ++j && ++k;
m = true || bla bla bla; //right not even checked!
m = true
m = 1
And you get the output as expected.
The logical && and || operators fully evaluate the LHS before doing any evaluation of the RHS.
In the code shown, since ++i is -2, the LHS of the || evaluates to true (1) and the RHS is not evaluated. Therefore, neither j nor k is incremented. The printed result follows: m was assigned 1, i became -2, and j stayed as 2 and k stayed as 0.
The only remaining issue is that && binds tighter than ||, so:
a || b && c
is equivalent to:
a || (b && c)
so if a evaluates to true (non-zero), then neither b nor c is evaluated.
Operator precedence is a completely different thing. Order of evaluation is determined by side effects and sequence points.
see this manual on order of evaluation.
This question already has answers here:
Why isn't "k" incremented in the statement "m = ++i && ++j || ++k" when "++i&&++j" evaluates to true? [duplicate]
(5 answers)
Closed 9 years ago.
#include<stdio.h>
int main()
{
int i=-3,j=2,k=0,m;
m= ++i && ++j || ++k;
printf("%d %d %d %d",i,j,k,m);
return 0;
}
Could someone tell how does is the m evaluated. I am confused as how k remain '0'
m= ++i && ++j || ++k;
First, ++i && ++j takes effect, i become -2 and j become 3, which makes ++i && ++j non-zero, so m will be evaluated to 1 (true) because of short-circuit. All the later expression(++k) won't be executed.
m= ( (++i) && (++j) ) || ++k;
| |
| |
( T (-2) AND T(3) ) OR something
^^^^^^^^^^^^^^^^^
T OR something
^^^^^^^^^^^^^^^^^^^^^^^^^
= T
= 0
Changing j=-1
m= ( (++i) && (++j) ) || ++k;
| |
| |
( T (-2) AND T(0) ) OR something
^^^^^^^^^^^^^^^^^
F OR T (0) //++k evaluated
^^^^^^^^^^^^^^^^^^^^^^^^^
= T
= 0
Initialized Values:
int i=-3,j=2,k=0,m;
Original expression:
m= ++i && ++j || ++k;
With implicit operator precedence:
m= (++i && ++j) || ++k;
The expression evaluates left to right. What you need to understand is how Short Circuit Logic works.
Evaluation Walkthrough:
i gets incremented (-3 --> -2)
The logical AND operator is evaluated (&&). It checks if the left hand argument i evaluates to true (i!=0). If the left hand side evaluates to false, the and operator short circuits the evaluation and returns false (0). This doesn't happen because i==-2, so the right hand side (++j) is also evaluated.
j get incremented (2 --> 3)
Logical AND finishes its right hand side evaluation i!=0 && j!=0. It returns true (!0).
The logical OR operator is evaluated (||). It checks if the left hand argument (++i && ++j) evaluates to true (!0). If the left hand side evaluates to true, the and operator short circuits the evaluation and returns true (!0). This happens because ++i && ++j already evaluated true. Consequent k++ never executes!
Logical OR (||) assigns the evaluated value (!0) to m. m!=0 after the expression evaluates.
This is because of short circuting. If you know about how an OR expression is evaluated, you will get the hang of this expression. 1 OR Anything is always 1
int i=-3,j=2,k=0,m;
m= ++i && ++j || ++k;
`-2 && +3 is +1 therefore +1 OR anything is 1.` Hence C skips evaluation of k.
the answer would be
-2 3 0 1
Explanation :
There are two basic facts that work here
FACT 1 :
Whenever there is an expression with PRE-INCREMENT operator, All these operators would be operated on the corresponding variables first, and then the whole expression would be evaluated with updated values of variables.
FACT 2
whenever there is an expression having OR operator, If first operator is true(or non zero in some cases), second operator wouldn't be executed.
for example
a=2;
b=2;
c=3;
boolean k = c || a+b ;
The values of variable k would be true and the expression "a+b" wouldn't be even considered as c is non zero.
In your case variable i and j would be incremented first and the expression would be
-2 && 3 || ++k
Note : variable k wouldn't be incremented here because in case of OR logical operator Left operand would be solved completely first.
Left operand would would be then TRUE because both -2 and 3 are non zero .
so the whole expression would be
TRUE || ++k
This wouldn't be evaluated further because no matter what, the result always be TRUE .
as we are assigning this result (TRUE) to an integer variable, it would be 1.
Hence the answer is ....
C newbie here, and I'm wondering, how come j is not incremented in the example below?
I searched everywhere for an explanation
int i, j, k;
i = 3; j=4; k=5;
_Bool checkbit;
checkbit = i < j || ++j < k;
printf("%d\n", checkbit );
printf("%d %d %d\n", i, j , k);
The output is
1
3 4 5
instead of
1
3 5 5
Thanks!
Because it doesn't need to be evaluated.
checkbit = i < j || ++j < k;
i < j will yield true, so no matter what the second part of the expression yields, the value of checkbit will be true. Thus, it doesn't even bother evaluating it.
Just for kicks:
checkbit = i > j && ++j < k;
In this case, the second expression will not be evaluated because false && (expr) is false.
Double-Or is "Shortcutting" - it won't evaluate the rest of the expression if the first part is true.
Use a single-or to increment it whatever happens.
This can be useful sometimes. It speeds up execution, because if the first part is true, you know the result of the or must be true!
Note that this is the same (in reverse) for &&: If the first part of && is false, then the second part is ignored, as you know the result will be false.
And it's perhaps worth mentioning that this behavior, short-circuit evaluation, is in the C standard:
6.5.14 Logical OR operator
Syntax
1 logical-OR-expression:
logical-AND-expression
logical-OR-expression || logical-AND-expression
Constraints
2 Each of the operands shall have scalar type.
Semantics
3 The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it
yields 0. The result has type int.
4 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.
(emphasis mine)
When using || operator, and the first condition evaluates to true, it ignores the rest unlike the && operator
checkbit = i < j || ++j < k; //since i < j is true, it skips over ++j < k