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.
Related
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
#include <stdio.h>
void main()
{
int i = -3, j=2, k=0, m;
m= ++i|| ++j && ++k;
printf("%d%d%d%d", i, j, k, m);
}
If we see order of evaluation in ++i|| ++j && ++k; we will come up with evaluation of ++j && ++k at first it will increment value of j and k and it will evaluate as 1 after that
++i || 1 will evaluate which will increment value of i and assign 1 to m so output should be -2 3 1 1 but it's giving output -2 2 0 1 I think i am missing some concept here.
|| and && are short-circuiting operators. They don't evaluate the second operand if it is not necessary to determine the output.
Here, ++i evaluates to a non-zero value, which is true in a boolean context. The right-hand side is not evaluated at all.
Since operator || and && are short circuit evaluated, once ++i is evaluated as true, ++j and ++k won't be evaluated. Thus, j and k are unchanged.
Logical operator always evaluates from left to right. These operators are known as short-circuit operator, i.e, if the value of the expression can be deduced from the value of the left operand alone, then right operand is not evaluated. Since i is non zero here, ++j && ++k is never evaluated and hence no modification is done to j and k.
Operator precedence has nothing to do with the order of evaluation. Do not get confused.
m will be equal to 1 since first , the OR condition is first evaluated, and as ++i is non-zero, you will get
m=1
as the first part of the OR statement itself is true, second part is not evaluated. So your j and k values will remain unchanged.
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
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.