If I have the following:
int a = -10 && 0;
then does C evaluate -10 as 1 because -10 is different from 0 and then make
the comparation between 1 && 0 to get 0 as result?
Or does let -10 and make the comparation as written?
Instead if I write:
int c = 10;
int b = 11;
int res = c > 10 && b == 11;
then the C make this:
c > 10 is false so it evaluates to 0 while
b == 11 is true so it evaluates to 1
then the expression is:
0 && 1 with 0 as result.
The operator && and || has short circuit behavior1. In
int a = -10 && 0;
since left operand is -10, which is non-zero and hence true, therefore right operand, i.e 0 is checked. In
int res = c > 10 && b == 11;
since left operand is evaluated to false, right operand is not evaluated.
1 C11 6.5.13 (p4): If the first operand compares equal to 0, the second operand is not evaluated.
For
int a = -10&&0;
-10 is treated as higher logic(1). However, result still be 0.
Related
I'm currently learning the basics of C programming language, but I can't seem to figure out how C understands the following code of operators. Below is the program, which prints "1, 1, 3, 0", while I think it should print "1, 1, 6, 0".
I've tried tweaking the line about y with the hypothesis that C language reads from the start, and once it saw !two, which is one, and the || operator, it said to itself, "Ah, whatever comes after || doesn't matter," and didn't assign 6 to one.
#include <stdio.h>
int main(void){
int one = 3, two = 1, x, y;
x = !!one && ((two = 0) != 0) || 3;
y = !two || ((one = 6) != 0) && !3;
printf("%d, %d, %d, %d", x, y, one, two);
}
So, I tried removing the ! in !two, switching the order around ||, which proved my hypothesis. However, when I switched ((one = 6) != 0) and !3, one is printed as 6. Now, I got no bright ideas as to how this happens.
Here
x = !!one && ((two = 0) != 0) || 3;
first !!one evaluated i.e first !one which is 0 and then again !0 which is 1 i.e true, next is logical AND && operator and && property is that if first operand is true then only check second operand, which is correct in our case.
x = !!one && ((two = 0) != 0) || 3;
| | |
true --------------
(1) |
solve this now
second operand of && is ((two = 0) != 0) which first makes two as 0(zero) and then 0!=0 which is false. Now it looks like
x = true && false || 3
| |
--------
|
false || 3 <= logical OR property is if 1st operand is false then need to check second operand.
x = false || true
x = 1
So after this expression x=1 and two=0.
Next, below expression
y = !two || ((one = 6) != 0) && !3;
First !two solved first i.e !0 i.e 1 that is true and logical OR || operator properties is that if first operand is true then second operands is not evaluated due to short circuiting. Hence it becomes
y = 1;
So after this expression
x=1 two=0 and y=1 rest all unchanged i.e one will be its initial value which is 3. So this
printf("%d, %d, %d, %d", x, y, one, two);
prints 1, 1, 3, 0
Side note, truth table of logical OR || operator
A B A||B
------------
0 0 0
0 1 1 => If 1st operand is zero, need to evaluate 2nd operand because 2nd operand may be 0 or 1
1 0 1 => if first operand is 1(true), result is always going to true, hence don't evaluate second operand
1 1 1
Truth table of logical AND && operator is
A B A&&B
------------
0 0 0
0 1 0 => If 1st operand is zero, result is always going to false, so need not to evaluate 2nd operand.
1 0 0 => if first operand is 1(true), Need to evaluate 2nd operand because 2nd operand may be 0 or 1.
1 1 1
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.
#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.
In the code below:
#include <stdio.h>
int main()
{
int a = 1;
int b = 1;
int c = a || --b;
int d = a-- && --b;
printf("a = %d, b = %d, c = %d, d = %d", a, b, c, d);
return 0;
}
i was expecting the output to be:
a=0,b=1,c=1,d=0
because due to short circuiting in the line below, ie a-- returns 0 so the other part wont get executed right?
int d = a-- && --b;
The output is:
a = 0, b = 0, c = 1, d = 0
can anyone please explain?
In first case
int c = a || --b;
After this a=1 , b=1 and c=1
a value is 1 , because of short circuit evaluation --b did not performed
int d = a-- && --b;
a-- is post decrement so decrement of a won't effect in expression
where as --b is pre decrement so effects here
Your condition becomes
int d= 1 && 0 ;
After this a=0; , b=0,c=1 and d=0.
int c = a || --b;
In this line, the C standard requires the C implementation to evaluate a first and, if it is not zero, not to evaluate --b. Although -- has higher precedence than ||, that just means that -- is grouped with b for the purposes of determining the structure of the expression, not for purposes of evaluating it. The left side of an || operator must be evaluated before the right side and, if the left side is true, the right side must not be evaluated, even in part.
So, after the above, b is not changed; it is still 1.
int d = a-- && --b;
As with ||, the left-hand side of the && is evaluated first. So a-- is evaluated. This changes a to 0. However, the value of a-- is a before the change, so it is 1. A value of 0 would prevent the right side from being evaluated (because, once we know the left side is zero, we know the value of the complete && expression is zero). But, since the left side is not zero, --b must be evaluated to finish the &&. This changes b to 0. “Short-circuiting” means the left side is evaluated first, but the right side is still evaluated when necessary.
In the first or operation, --b is not executed since a equals 1:
int c = a || --b;
But b is decremented here:
int d = a-- && --b;
Because a equals 1 and is decremented after it is evaluated (a-- equals 1). In other words, this line is similar to:
int d = 1 && --b;
b was equal to 1 so now b equals 0 now. And d also equals 0 because --b returns 0.
the line below, ie a-- returns 0
No, it doesn't. It yields 1, as the post-decrement operator evaluates to the unmodified value of the variable. What you are thinking about is perhaps --a.
c = a || --b
so at first a is evaluated and a value is 1 which is true. So compiler does not evaluate --b. So b value is still 1
Now
d = a-- && --b
a-- && --b => 1 && 0 (since --b = 0 ) since b value is at 1.
why 1 because a-- is post decrement operator
Why 0 because --b is pre decrement operator
so 1 && 0 returns 0 and this value is stored in d
So the output: a = 0, b = 0, c = 1, d = 0
You're mixing up a-- with --a. The result of the expression a-- is a before the decrement, while --a is a after the decrement; in other words:
int a = 1;
int b = a--; // b == a == 1
int c = --b; // c == b-1 == 0
As a result, you have:
int d = a-- && --b;
// => 1 && b-1
// => 1 && 0
// => 0
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.