I can't figure out how will this expression be evaluated in C?
I'm a bit confused with the evaluation of an expression inside printf?
If an expression inside printf evaluates from right to left then the evaluation of expression should've stopped after encountering (c>10), but it printed '1' to the output screen?
This is not exact syntax of C, but a question that was asked to me.
integer a = 50, b = 25, c = 0;
printf( a > 45 || b > 50 && c > 10 );
This expression
a > 45 || b > 50 && c > 10
is equivalent to expression
( a > 45 ) || ( b > 50 && c > 10 )
Thus if this subexpression ( a > 45 ) evaluates to true then the second subexpression will not evaluate and the result is equal 1 (of type int).
Otherwise this sub expression
( b > 50 && c > 10 )
is equivalent to
( b > 50 ) && ( c > 10 )
if ( b > 50 ) evaluates to false then the whole result is false (0 in C) and the second subexpression will not evaluate. Otherwise the result is the value of
the subexpression c > 10. If c > 10 then the result is an object of type int with value 1 or if not ( c > 10 ) then the value of the result is 0.
If the variables have values as it is shown in your question
int a = 50, b = 25, c = 0;
then the first subexpression
a > 45
evaluates to true and the result is 1 of type int. The second subexpression
b > 50 && c > 10
will not even evaluate.
Consider the following demonstrative program
#include <stdio.h>
int f( int x )
{
printf( "f is called for %d\n", x );
return x;
}
int main( void )
{
int a = 50, b = 25, c = 0;
f( f( a ) > 45 || f( b ) > 50 && f( c ) > 10 );
return 0;
}
Its output is
f is called for 50
f is called for 1
As you can see it was enough to calculate the expression f( a ) > 45 to get the result equal to 1.
It would be undefined behaviour. The first argument to printf must be a format string. Most likely it will crash. What saves you is that "integer" is not a type, so it's not going to compile.
Both the || and && operators force left-to-right evaluation. The left-hand operand will be fully evaluated (and all side effects applied) before the right-hand operand is evaluated.
Furthermore, both operators short-circuit - depending on the value of the left-hand operand, the right-hand operand may not be evaluated at all.
For
a || b
if a is true, then the entire expression is true regardless of the value of b, so b isn't evaluated.
Similarly, for
a && b
if a is false, then the entire expression is false regardless of the value of b, so b isn't evaluated.
&& has higher precedence than ||, so
a || b && c
will be parsed as
a || (b && c)
and
a && b || c
will be parsed as
(a && b) || c
So...
a > 45 || b > 50 && c > 10
is parsed as
a > 45 || (b > 50 && c > 10 )
Since a == 50, a > 45 is true. Since a > 45 is the left-hand operand of the || operator, the whole expression is true regardless of the right-hand operand, so b > 50 && c > 10 isn't evaluated at all.
The result of expression is 1 (true).
Unfortunately, printf expects its first argument to point to a character string (the format string), and 1 is most likely not a valid address on your platform, so the result of this code will most likely be a segfault. The easy fix would be to write
printf( "%d\n", a > 45 || b > 50 && c > 10 );
The context in which an expression appears affects whether it is evaluated, but not how. The order in which subexpressions of a larger expression are evaluated is controlled by operator precedence and associativity.
Among the operators in your expression, > has greatest precedence, then &&, then ||. All associate from left to right. Therefore, your expression is evaluated exactly the same as if it were written like so:
(a > 45) || ((b > 50) && (c > 10))
Furthermore, the && and || operators perform short-circuit evaluation. This seems to be a point of confusion for you. Short-circuit evaluation means that if the result of an && or || operation is determined by the value of the left-hand operand, then the right-hand operand of that operation is not evaluated. That does not affect whether or how other operations are evaluated, except to the extent that the result of the short-circuited operation is used as an operand.
In this case, however, because || associates left-to-right, a > 45 is evaluated first, producing 1 (true). Because this determines the result of the || operation, its right-hand operand is not evaluated. Relative operator precedence yields the right-hand operand being the remainder of the overall expression, as shown above, so none of that will be evaluated. Even if it were evaluated, however, the result of the overall expression would still be 1, because the left-hand operand evaluates to 1, regardless of the right-hand sub-expression. That's why the right-hand side of the || does not need to be evaluated.
Related
This question already has answers here:
What is short-circuit evaluation in C?
(3 answers)
Closed 2 years ago.
I want to ask a question about the code below.
int a=1, b=3, c=1;
if((a||c--)&&(c&&b--)) printf("%d",b);
printf("%d %d %d",a,b,c);
Why does the code prints "21 2 1" rather than "1 2 0" ?
Thanks for your help.
Since the or is evaluated to true immediately in (a||c--), the c-- is never evaluated. The compiler does this. If a statement is true right off the bat, it won't bother evaluating the rest. So, c is never decremented as the right side of the or is never evaluated.
Both || and && force left-to-right evaluation - the LHS is evaluated first and all side effects applied, then based on the result the RHS is evaluated.
Both operators short-circuit:
for a || b, if a is non-zero, then the result of the expression is 1 regardless of the value of b, so b is not evaluated;
for a && b, if a is zero, then the result of the expression is 0 regardless of the value of b, so b is not evaluated.
&& has higher precedence than ||, so a || b && c is parsed as a || (b && c).
Putting all that together, (a||c--)&&(c&&b--) is evaluated as follows:
a || c-- is evaluated as follows:
a is evaluated - its result is 1, so
c-- is not evaluated; because of this c's value is not changed, and
the result of the expression is 1
c && b-- is evaluated as follows:
c is evaluated - its result is 1, so
b-- is evaluated - its result is 3; as a side effect b is decremented, and
the result of the expression is 1
both a || c-- and c && b-- evaluate to 1
The values of a and c are unchanged (1 and 1, respectively), while b has been decremented and its value is now 2.
You can imagine this if statement
if((a||c--)&&(c&&b--)) printf("%d",b);
the following way
if ( a )
{
if ( c )
{
if ( b-- )
{
printf("%d",b);
}
}
}
else if ( c-- )
{
if ( c )
{
if ( b-- )
{
printf("%d",b);
}
}
}
So if the expression in the first if statement
if ( a )
evaluates to the logical true then this if statement
else if ( c-- )
never gets the control.
From the C Standard (6.5.14 Logical OR operator)
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.
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>
main()
{
int x = 1, y = 0, z = 5;
int a = x && y || z++;
printf("%d", z);
}
This code gives me output : 6
#include <stdio.h>
main()
{
int x = 1, y = 0, z = 5;
int a = x && y && z++;
printf("%d", z);
}
This code gives me output : 5
Why the second program gives ouput as 5 even though z was incremented same like in first program?
The && operator (as well as the || operator) is a short-circuit operator. That means that if the left operand evaluates false, the result is false regardless of the right operand, so the right operand is not evaluated.
From section 6.5.13 of the C standard:
4 Unlike the bitwise binary & 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 equal to 0, the second operand is not evaluated.
So in the case of this expression:
x && y && z++;
x && y is evaluated first. Since x is 1, y is evaluated and found to be 0, so the result of the first && is 0. Now we have:
0 && z++
Since the left operand is 0, the right operand is not evaluated. This means that z is not incremented.
This is in contrast to expression in the first piece of code:
x && y || z++
As before, x && y evaluates to 0, leaving us with:
0 || z++
Since the left operand is 0, the right operand needs to be evaluated. This results in z getting incremented.
Evaluation of x && y && z++ stops after y because y==0. z++ is not executed.
The initializer in this declaration
int a = x && y || z++;
is equivalent to
int a = ( x && y ) || ( z++ );
According to the C Standard relative to the logical OR operator (6.5.14 Logical OR operator)
4 ... If the first operand compares unequal to 0, the second operand is
not evaluated.
However the first operand that is ( x && y ) compares equal to 0 (due to the variable y is equal to 0). So the second operand ( z++ ) is evaluated.
The initializer in this declaration
int a = x && y && z++;
is equivalent to
int a = ( x && y ) && ( z++ );
According to the C Standard relative to the logical AND operator (6.5.13 Logical AND operator)
4 ...If the first operand compares equal to 0, the second operand is
not evaluated
So as the first operand ( x && y ) compares equal to 0 then the second operand ( z++ ) is not evaluated.
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.
I know that Java and C/C++ have short circuit evaluation, i.e., in if (a && b), b will never evaluated if a is not true.
But what if I have expression like if ( (a && b) OP c ) (where OP is an arbitrary logical operator), will b evaluated if a = false? Thanks.
C Standards say that -
6.5.13 Logical AND operator
The && operator guarantees left-to-right evaluation......
.If the first operand compares equal to 0, the second operand is not evaluated.
So in case a==flase b will not be evaluated.
You will always have if a = false : a && b == 0 whatever the value of b. Why would an operation done after the evaluation will change that ?
a b | a && b
0 0 | 0
0 1 | 0
If a=false then condition for b will not be checked so (a && b) is ALWAYS false
and the next condition depends upon the OP used if it is && it will not be evaluated. If it is || it will be evaluated.
So
((a && b) OP c)
here if a=false (a && b) will be always false.