In the code below, I was expecting answer 'Yes'. But the answer is no. That means i is getting incremented after && operation. I was expecting that i gets incremented once entire expression inside if() is evaluated. So what are the rules associated with post increment?
int main()
{
int i = 1;
if (i++ && (i == 1))
printf("Yes\n");
else
printf("No\n");
}
The logical AND operator && has a sequence point between the evaluation of the left operand and the right operand. That means the left operand is evaluated first, along with any side effect (in this case the increment).
In this expression, i starts with a value of 1. So the expression i++ has a value of 1, and the value of i is incremented.
As the left side of the && operator this value evaluates to true, so the right side is then evaluated. If the value was 0 i.e. false the right side would not be evaluated.
At this point the value of i is 2, so i == 1 evaluates to false, making the result of the && operator false. This results in the else clause being executed.
it compiles from left to right, up to down, so it's logical that you're having a 'No', your if statement contains i++ which will cause i to be equal to 2 and then returns true, then it contains i==1 which will return false since i is no longer equal to 1, so your if statement is returning false which will make it execute what's on the else, means 'No'.
A simple explanation about logical operators:
&&: evaluated from left to right, and all the evaluated conditions must return 'true' so it can be true.
||: evaluated from left to right as well, except that it ends the evaluation with true, once finding one true condition.
Related
I'm reviewing material on C. I'm not sure why the answer is 12 and 32. In the first printf(), I thought that %d = 2 (i), %d = 2 (j), \n = new line. Can anyone explain this?
#include <stdio.h>
int main(void) {
int i,j;
i=2 && (j=2);
printf("%d%d\n",i,j);
(i=3) || (j=3);
printf("%d%d\n",i,j);
}
For the first expression, i=2 && (j=2); is implicitly evaluated as i = (2 && (j = 2)); because the assignment operator = has lower precedence compared to the logical operators. In the first condition, 2 has the truth value of true, and logical AND && causes all conditions to be evaluated, meaning j = 2 is also evaluated, assigning 2 to j and returning 2 which evaluates to true. So now the actual expression to be evaluated is i = 2 && 2; which is true, or in C's terms, 1. So, i is assigned 1, and the first output is 12.
For the second expression (i=3) || (j=3);, the logical OR || is used, and short circuiting ensures that if the first condition evaluates to true, the overall expression is true and so the second condition is not evaluated. So after i = 3 is evaluated, i is assigned 3 and the entire expression is true, so j = 3 is not evaluated. And so the second output is 32.
Based on precedences, the first expression is evaluated as
i = (2 && (j=2));
So i=1 (true) and j=2. That is why the first output is 12.
The second expression is a logical OR of two assignments.
(i=3) || (j=3);
But since the first evaluation from left is "true" (i=3) the second evaluation is not done. That is why value of j remains 2 and the second output is 32 (not 33).
The reason 12 is printed instead of 22 is because i is assigned the value of 2 && (j=2). First j gets assigned to 2. Then (j=2) returns 2. After that 2 && 2 is evaluated to true, and it returns true. This is because && checks if both sides are true, and 2 is interpreted as true. Since both sides are true, it returns true which is 1.
The || does not evaluate right hand side if left is evaluated to true. The reason is that it is not necessary. It should evaluate to true if at least one of the operators evaluates to true, and i=3 evaluates to 3 which is interpreted as true. That's why 32 is printed instead of 33.
The feature that it does not evaluate right operand if left evaluates to true can be used to do this:
foo() || printf("foo() returned false\n");
And similar for &&, but this operator does not evaluate right operand if left evaluates to false.
foo() && printf("foo() returned true\n");
Note that I'm not suggesting that these tricks should be used. I'm just using them as an example of how || and && may skip evaluating the right operand depending on the value on the left.
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.
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
I came across a question and I wanted to verify whether my assumptions were correct.
Given the following codes:
1. int i = -2, j = 1, ans;
2. ans = i++ || ++j;
3. printf("%d %d %d", i,j, ans);
The output is: -1 1 1
In C language, it seems that only 0 will be treated as false, any other values will be treated as true when used with a logical operator. So I am not doubtful why ans derives to 1 (true || true gives us true(1) )
What I wanted to ask here is: Why is the value of j still 1 and not 2 despite ++j?
Can safely assume that any arithmetic operations after the logical operators || && will only be effective at the line it is used(in this case, line 2), and after which the variable still retain its original value?
|| operator wont do any operation on second operand when first operand is nonzero.
Because, any one of the operand is non-zero then, output will be true in || operator operation. In your code 1st operand is non-zero. Thats why operation on second operand is not performed.
As in Second Line of your Code i.e
ans = i++ || ++j;
first it will check i++ as it is not zero that means it is true.
And in OR Condition if first condition is true it will not check second condition i.e ++j.
Because if first condition is true is doesn't matter, Second condition is TRUE or FALSE it will return a true value. So if First Condition is true it will not check the other condition.
Logical operators short circuit. That is, in the following:
ans = i++ || ++j;
++j will never be evaluated if i++ evaluates to true (non-zero).
Consider this code:
int a = 5;
if (a == 5 || a == 10)
doSomething();
In this case a is 5 so the first condition is true. Will the program check if the second condition is true or it will start executing doSomething() immediately after it makes sure that a is really 5?
It will start executing immediately. This is known as short-circuit evaluation.
http://en.wikipedia.org/wiki/Short-circuit_evaluation
The second condition won't be checked. C short-circuits logical evaluations, so as soon as the truth or falsehood of the condition can be determined it stops.
Note that given the code as posted, the compiler might not even generate code to perform the first comparison as it can determine at compile time that the condition is satisfied and no intervening code could alter the value of a.
Share and enjoy.
int a = 5;
if (a == 5 || a == 10)
doSomething();
in this example the left operand operand of || is evaluated to 1 so the right operand will not evaluated.
The compiler is required to not evaluate the right operand of || operator when the left operand is evaluated to 1.
When it comes to the logical operations, the compiler will stop evaluating the expression as soon as its finds the truth or falsehood of the expression.
The truth-table for logical or (||) operation is as follows:
A B A||B A&&B
0 0 0 0
0 1 1 0
1 0 1 0
1 1 1 1
So for an expression like a == 5 || a == 10, when a is equal to 5, the expression will be evaluated to true when the compiler sees a == 5 part. So irrespective of whether the rest of the expression is evaluated to true or false, due to the logical or (||) operator (refer the above truth-table), this expression will be evaluated to true. So the compiler will discard executing the rest of the expression.
Any decent compiler will not even check the first condition since at compile time it knows at once that it should invoke your method. (but of course all comments about short circuit hold true - but not here ;-)