I was working on the Basics of C and was trying to solve the problem below could any one explain why the output of variable c is different?
What is the output of the following program?
int main()
{
int a = -3, b = 2, c= 0, d;
d = ++a && ++b || ++c;
printf ("a = %d, b = %d, c = %d, d = %d", a, b, c, d);
}
Ans: -2, 3, 0, 1
Why c is not incremented in the output ?
The variable c is not incremented because the RHS (right-hand side) of an || is not executed unless the LHS evaluates to false, and the LHS evaluates to true. The C || and && operators are 'short-circuit' operators; they do not evaluate the second operand unless the first is insufficient to determine the overall truth of the expression.
The && binds tighter than the ||, so the operation can be parenthesized as:
d = (++a && ++b) || ++c;
The value of ++a is -2, which evaluates to true (because any value that is not 0 evaluates to true); the value of ++b is 3, which evaluates to true; so the value of the && term is true. Because true || false and true || true both evaluate to true, there is no need to evaluate the RHS to know the overall result. (The analogous rule for && is that if the first term evaluates to false, there is no need to evaluate the second because the overall expression must be false. If you had a = -1; before the test, then b would not be incremented, because ++a would be zero or false, so the RHS of the && is unevaluated. Of course, then c would be incremented because the LHS of the || would be false, and the RHS would have to be evaluated to determine the overall result.)
Because ++a && ++b evaluates to true.
It's called short-circuiting. Expressions inside conditions are evaluated from left-to-right. If your case, if the first condition in the OR clause is evaluated to true, there's no point for the second one to also be evaluated, since the whole expression is known to be true already.
In C, the boolean logic operators && and || are short-circuiting. This means that they only evaluate their right side, if evaluating the left side is not enough to know the answer.
For your code, this has the effect of never evaluating ++c, since the left-hand side is not zero and thus the boolean or's result will be true, and there's no need to do more work.
It is lazy boolean expressions evaluation.
The execution is:
++a gives -2
++b gives 3
-2 && 3 gives 1
Okay! No need to check result of ||. So ++c is not evaluated.
The rule is: expression part X is not evaluated in cases: (0 && X), (1 || X). Here 1 is "not 0" of course.
d= ++a && ++b || ++c
d= ++(-2) && ++b || ++c
d= -1 && ++b || ++c
d= true && ++b || ++c
d= true && ++2 || ++c
d= true && true || ++c
d= true || ++c
d= 1
That's roughly how it works behind the scene...
Related
Logical OR and Logical AND operator on integers in C
Can you explain me why the values of a,b,c are 11,10,1 respectively.
Why the value of b remains same as 10?
#include <stdio.h>
int main()
{
int a,b,c;
a=b=c=10;
c = a++ || ++b && ++c;
printf("%d %d %d",a,b,c);
return 0;
}
First, let's look at the order of operations. The logical AND operator && has higher precedence than the logcial OR operator ||, so the expression parses as follows:
c = a++ || (++b && ++c);
Next, both || and && are short circut operators. This means that the left has side is evaluated first, and if the result can be determined solely from that then the right hand side is not evaluated.
So a starts out with the value 10. a++ evaluates to the current value (10) while incrementing a as a side effect. This means the value 10 is the left hand side of ||. Because this is a non-zero value, the value of the entire expression is 1 and the right hand side ++b && ++c is not evaluated. Then this result is assigned to 1.
So the end result is a is incremented to 11, c is assigned 1 because that is the value of the || expression, and b is unchanged.
This expression
c = a++ || ++b && ++c;
can be equivalently rewritten like
c = ( a++ ) || ( ++b && ++c );
As the expression a++ is not equal to 0 then the second sub-expression ( ++b && ++c ) is not evaluated.
The value of the logical operator || and && is either 1 (true) or 0.
From the C Standard (6.5.14 Logical OR operator)
3 The || operator shall yield 1 if either of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
and
4 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.
So c gets the value 1 and a was increased.
Expanding, a little bit, on the other answers, you have to understand what your statement is actually doing.
a=b=c=10;
c = a++ || ++b && ++c;
The logical operators take, naturally, boolean operands, so your statement is (implicitly):
c = ( a++ != 0 ) || ( ++b != 0 ) && ( ++c != 0 );
Note, interestingly, that the order of precedence places the AND operator higher than the OR operator - which implies that ++b should be executed.
However, given the short-circuit operation of logical-OR, the first term is known to be true therefore c = 1 (ie true).
--
Regular readers will, of course, expect me to add a MISRA slant to my answer...
MISRA C:2012 Rule 13.5 covers this exact scenario... it states that The right hand operand of a logical && or || operator shall not contain persistent side effects
So a MISRA Compliant version of your code would be:
a=b=c=10;
a++;
b++;
c++; // This is actually *dead code*
c = a || ( b && c );
printf("%d %d %d",a,b,c);
This question already has answers here:
Is short-circuiting logical operators mandated? And evaluation order?
(7 answers)
Closed 5 years ago.
#include <stdio.h>
int main(){
int a=5,b=-7,c=0,d;
d=++a && ++b || ++c;
printf("%d %d %d %d",a,b,c,d);
}
Here value of c should increase to 1 but it is giving 0, why?
It's because of short-circuiting. If you have a && b, then b will only be evaluated if a is true. Similarly, if you have a || b, then b will only be evaluated if a is false.
In your case, ++a && ++b || ++c groups as (++a && ++b) || ++c. First ++a is evaluated, and it's true, so ++b is evaluated, and it's also true. At this point, evaluation stops because it is now certain that the result of the || operator is true, so ++c is never evaluated.
Because the || doesn't evaluate the right hand side if the left hand side evaluated to true. In your example,
++a && ++b
evaluates to non-zero, which is treated as a true. Therefore, according to the rules of lazy evaluation, the ++c is completely ignored.
I have a problem with a question in my book:
#include<stdio.h>
void main()
{
int a=5, b=-7, c=0, d;
d = ++a && ++b || ++c;
printf("\n%d%d%d%d",a,b,c,d);
}
The question asks me what is the output of the code. I ran it and the result on the screen is 6-601. I understand why a=6 and b=-6, but I don't understand why c=0 and d=1?
I believe you already got your answer, but just to elaborate a bit step-by-step, let me add one more clarification here. Firstly, to quote the properties of the && and || operators, from C11 standard, chapter §6.5.13 and §6.5.13, respectively,
(I)
The && operator shall yield 1 if both of its operands compare unequal to 0; otherwise, it
yields 0. [...] If the first operand compares equal to 0, the second
operand is not evaluated.
and
(II)
The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it
yields 0. [...]. If the first operand compares unequal to 0, the second operand is
not evaluated.
and they both guarantee left-to-right evaluation. So, comparing your code,
d = ++a && ++b || ++c;
it happens like
d = ((++a && ++b) || ++c );
which evaluates to
d = (( 6 && ++b ) || ++c);
and then
d = ( ( 6 && (-6) ) || ++c);
Now in above stage, (I) is fulfilled and it comes down to
d = ( 1 || ++c);
Now, following the emphasis, which already meets the (II), so no further evaluation of the RHS operand of || is performed (i.e., ++c is not evaluated), and it appears to be d = 1 and the final result, 1, is stored into d.
That's how, a == 6, b == -6, c == 0 and d ==1.
Having said that, void main() should be changed to int main(void), at least to conform with the standard.
The || OR operator is short-circuiting, which means that if the left side is true then the right side is not evaluated. In this case ++a && ++b evaluates to true, so ++c is never run and c keeps its value of zero.
Also since it evaluates to true, this is denoted with 1 which is stored in d.
Any non-zero value is considered to be true and the result of boolean operations is defined to be 0 or 1 as an integer.
As far as I'm aware of, unary operators have prior precedence over || and &&. In the following code, I'd expect an output where all outputs are equal to 1. Yes, there is a short-circuit but shouldn't those pre-increments calculated before || and &&? How these precedences work here?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 0, b = 0, c = 0;
a = b = c == 1;
c = ++a || ++b && ++c; // short-circuit here
printf("a=%d, b=%d, c=%d\n", a, b, c);
}
Output:
a=1 b=0 c=1
Operator precedence doesn't have any relation with order of evaluation. Higher precedence means that grouping of operands to that operator is done first.
In the statement
c = ++a || ++b && ++c;
the grouping/binding of the operands of ++ will be done first and then that of && and || respectively. To show this I am adding parenthesis to the expression
++ has higher precedence so bind operand to it first
c = (++a) || (++b) && (++c);
&& has higher precedence than ||
c = (++a) || ((++b) && (++c));
|| has higher precedence than =
c = ((++a) || ((++b) && (++c)));
= has least precedence of all
(c = ((++a) || ((++b) && (++c))));
The fact that || is short-circuiting and the lowest precedence operator explains the result. Because ++ is the higher precedence than && and && is higher precedence than ||, the expression tree for ++a || ++b && ++c is:
|| -- left: ++a
-- right: && --left: ++b
--right: ++c
So, to evaluate the expression, C first considers the rules for evaluating ||, given by 6.5.14 in the C11 standard. Specifically:
6.5.14.4: 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.
The fact that || is short-circuiting means that it evaluates its left operand first and only evaluates its right operand if the left is zero. So to evaluate the expression ++a || ++b && ++c, C requires the following:
Evaluate ++a (a is incremented by one and the expression is equal to its incremented value). If it is non-zero, then || expression is equal to 1 and the right side is never evaluated.
Otherwise, evaluate ++b and ++c, in left-to-right order. If ++b is zero, then ++c is never evaluated. If both are non-zero, then the expression is equal to 1.
Because ++a evaluates to 1, the right side of the || is never evaluated. This is why you have a==1, b==0, and c==1.
There's one additional problem with the statement c = ++a || ++b && ++c, which is that there's a potential for the statement to invoke undefined behavior. If ++a is false and ++b is true, then ++c has to be evaluated. However, there is no sequence point between c = ... and ++c. Since the expressions both modify c with no sequence point in between, the behavior is undefined. For a further explanation of this see, for example, https://stackoverflow.com/a/3575375/1430833
I think you're confusing operator precedence with order of evaluation. Here's an outline of what happens. In the comments, my use of = is that of identity - much like the mathematical equals sign.
#include <stdio.h>
#include <stdlib.h>
int main()
{
// all variables are assigned the value 0
int a = 0, b = 0, c = 0;
// a and b are equal to the evaluation of `c == 1`, which is false. a and b are 0
a = b = c == 1;
/*
&& has higher precedence than ||, so ++b and ++c are "grouped": ++a || (++b && ++c)
++a is evaluated, a = 0+1 = 1. 1 is true, short circuit the second grouping.
c = a = 1.
*/
c = ++a || ++b && ++c; // short-circuit here
// a = c = 1, b = 0
printf("a=%d, b=%d, c=%d\n", a, b, c);
}
#include <stdio.h>
void main()
{
int a = 5, b = -7, c = 0, d;
d = ++a && ++b || ++c;
printf("\n %d,%d,%d,%d", a, b, c, d);
}
In the above code, the output is 6,-6,0,1. Why is the value of c 0 and the value of d 1?
how did d get the value as 1?
That is because || first checks the left part and if it is true it return true without evaluating the right part.
In C any non zero is treated as True and zero as False
int a = 5, b = -7, c = 0, d;
d = ++a && ++b || ++c;
Here ++a and ++b are non zero and both are treated as True so ++a&&++b becomes True and the expression stops evaluating over there.
There are already good answers that explain why c is 0 after the line
d = ++a && ++b || ++c;
is executed.
The line is equivalent to:
d = (++a && ++b || ++c);
That explains why d is 1.
int a = 5, b = -7, c = 0, d;
d = ++a && ++b || ++c;
let's analyze the statement part by part
++a : a=6
++a && ++b: b becomes -6 ,and then it does : 6 && -6 ,which is equal to 1
now there is a || (or symbol) ,but this cannot affect the value of d since
1||"value2" =1 ,
so the compiler does not evaluate "++c" .
so c remains 0 and d becomes 6 && -6 =1
&& has higher precedence than || so first ++a&&++b is evaluated first and it becomes true. The expression becomes true || ++c and || will evaluate from left to right since || encounters true and it returns 1 to d without evaluating ++c. So c value will not be incremented
An evaluation tree is created which does the evaluation. The || part is parent and the two parts on its side are its parents. When it evaluates one child, if it gets true, it doesn't evaluate the other child.