#include<stdio.h>
void main() {
int x = 0,y = 0,k = 0;
for(k = 0; k < 5; k++){
if(++x > 2 && ++y > 2) x++;
}
printf("x = %d and y = %d",x,y);
}
I'm not able to understand how the above piece of code generates x = 6 and y = 3.
RESOLVED : I didn't know that when there is &&, if the first statement evaluates to false the second will not be executed.
&& is a short-circuit operator.
The first time through the loop, only ++x is evaluated.
The second time through the loop, only ++x is evaluated.
The third time through the loop, both are evaluated.
...
Not related to your question, but please read What should main() return in C and C++? int.
c enables short circuit, and && is an operator that follows that. So, this:
if(++x > 2 && ++y > 2)
says:
Increment x by 1.
If x is greater than 2 (thus the first operand of && is true),
evaluate the second operand.
The second operand says to increment y by 1, and if y > 2 is
true, then the whole if condition will be true.
Your code is equivalent to this:
#include <stdio.h>
int main() {
int x = 0, y = 0, k = 0;
for(k = 0; k < 5; k++){
x = x + 1;
if(x > 2)
{
y = y + 1;
if(y > 2)
{
x = x + 1;
}
}
}
printf("x = %d and y = %d", x, y);
return 0;
}
&& is the short-circuit operator.
if ( ++x > 2 && ++y > 2 )
in this if statement the second operand will be evaluated only if the first one is true.
when k=0 X will be incremented by 1. Now x value is 1. x > 2 is false. So Y won't increase.
When k=1 X will be incremented by 1 . Now X value is 2 . X > 2 is false. So Y won't increase.
when k=2 X will be incremented by 1 . Now X value is 3 . X > 2 is true . So Y will be incremented by 1 . Now Y value is 1 . but Y > 2 is false . So total if condition is false.
when k=3 X will be incremented by 1 . Now X value is 4 . X > 2 is true . So Y will be incremented by 1 . Now Y value is 2 . but Y > 2 is false . So total if condition is false.
when k=4 X will be incremented by 1 . Now X value is 5 . X > 2 is true . So Y will be incremented by 1 . Now Y value is 3 . Y > 2 is true . So total if condition is true. Then X will be incremented by 1.
The final answer is X=6 and Y=3 .
if(++x > 2 && ++y > 2)
In this line if first condition is false it will not evalute second condition. So first condition is false until value of x is 3
Related
can any one help me understanding the output of this code?
#include <stdio.h>
int main()
{
int x = 1, y = 1;
for(; y; printf("%d %d \n", x, y))
{
y = x++ <= 5;
}
return 0;
}
the output is:
2 1
3 1
4 1
5 1
6 1
7 0
A for loop in the form of
for (a; b; c)
{
d;
}
is equivalent to
{
a;
while (b)
{
d;
c;
}
}
Now if we take your loop
for(; y; printf("%d %d \n", x, y))
{
y = x++ <= 5;
}
It is equivalent to
{
// Nothing
// Loop while y is non-zero
while (y)
{
// Check if x is less than or equal to 5, assign that result to y
// Then increase x by one
y = x++ <= 5;
printf("%d %d \n", x, y);
}
}
Now it should hopefully be easier to understand what's going on.
Also: Remember that for boolean results (like what you get as result from a comparison), true is equal to 1, and false is equal to 0.
The code is an obfuscated, ugly version of this:
#include <stdio.h>
#include <stdbool.h>
int main()
{
int x = 1;
bool y = true;
while(y == true)
{
y = (x++ <= 5);
printf("%d %d \n", x, (int)y);
}
return 0;
}
y in the original code serves as a boolean. Back in the ancient days, there were no boolean type in C so it was common to use int instead. The expression y = x++ <= 5; evaluates to 0 or 1, which is equivalent to false or true.
Note:
While the C language allows all manner of crazy stuff, you should never write for loops as in the original code. De facto standard is to write for loops like this:
The first clause of a for loop shall only contain iterator initialization.
The second clause should only contain the loop condition.
The third clause should only contain a change of the loop iterator, such as for example an increment (like i++).
A for loop that doesn't follow the above industry standard rules is badly written, no excuses.
The statement y = x++ <= 5; sets y to 1 if x is less than or equal to 5, or to 0 if x is greater than 5. It then increments x. The loop stops when y is equal to 0, that is, on the iteration after x was incremented above 5. Then it runs the printf() statement on each iteration.
You wouldn’t normally see a loop switch the loop condition and the loop body that way. This seems to be a pathological example of how it’s technically legal. You shouldn’t imitate it.
y is 1 (true) as long as x <= 5 and x increases every iteration.
Rewrite your code:
for (int x = 1, y = 1; y; y = x <= 5, x++) {
printf("%d %d\n", x, y);
}
or using while
int x = 1;
int y = 1;
while (y) {
printf("%d %d\n", x, y);
x++;
y = x <= 5;
}
The first component of the for loop is empty; which means values of variables haven't changed. The condition in the for loop is y. Which means that the loop will run till the condition y is true; which means till the value of y is anything other than 0.
When the value of y becomes equal to 0; the condition will become false and the loop will stop iterating.
Then comes the block execution...
y = x++ <= 5;
Here first the condition x <= 5 is checked. Note that x++ is post increment and so the value of x will be incremented after the execution of the statement. So, if the value of x was 1 before increment; it will check 1 <= 5 and not 2 <= 5 and after the execution of the statement; the value will become 2.
After that comes the third component of for loop which is the increment part. Here,
printf("%d %d \n", x, y)
simply prints x and y.
So, what happens is; when the loop starts, both x and y are 1.
The statement
y = x++ <= 5;
is encountered, thus the condition x++ <= 5 is checked, where x is 1. Since the condition is true; the value of y will be 1 and x will be incremented to 2. The same thing continues.... when x will be equal to 5, x++ <= 5 will check 5 <= 5 and the condition will be true and x will be incremented to 6. Now when it goes in the loop the next time; the condition will be false and y will instead be equal to 0. Thus, now when the loop checks the condition y, the condition will be false and thus the control will flow out of the loop and thus you see the result.
I built and dumped this code in IDA since I understand assembly better :D
This code is a bit obfuscated so here will be the normal version of it:
#include <stdio.h>
int x = 1;
int y = 1;
while(y != 0) {
if(x++ <= 5)
{
y = 1;
} else {
y = 0;
}
printf("%d %d\n",x,y);
}
that for loop in the source:
for(; y; printf("%d %d \n", x, y))
checks if y is a non-zero value and if it is, it will print the string you want. In the body of the loop, the result of the comparison (0 or 1) will be copied to y and the check continues.
Precedence of operator <= is higher than the operator =.
So, the statement:
y = x++ <= 5;
is equivalent to:
y = (x++ <= 5)
Because of post-increment ++ operator, the value of x returned first and then x is incremented.
The initial value of both x and yis 1.
Since y is 1, the for loop condition evaluates to true and the statement in the for loop block executed. But in the for loop of your code, in place of loop iterator update statement you have printf() statement which is printing the value of x and y after executing the loop body statements. The flow goes like this:
1 <= 5 evaluate to 1 which is assigned to y and after this x is 2,
Output : 2 1
2 <= 5 evaluate to 1 which is assigned to y and after this x is 3,
Output : 3 1
3 <= 5 evaluate to 1 which is assigned to y and after this x is 4,
Output : 4 1
4 <= 5 evaluate to 1 which is assigned to y and after this x is 5,
Output : 5 1
5 <= 5 evaluate to 1 which is assigned to y and after this x is 6,
Output : 6 1
6 <= 5 evaluate to 0 which is assigned to y and after this x is 7,
Output : 7 0
Now the value y is 0 and in your code, the for loop condition is y so the loop condition evaluates as false and loop exits.
This question already has answers here:
Why is a condition like (0 < a < 5) always true?
(4 answers)
Closed 9 years ago.
I have this question & in the answer it says that due to left to right associativity the result would be 1 that is true for this statement. This is the code.
#include<stdio.h>
int main ()
{
int i=0,x=10,y=10,z=5;
i=x<y<z;
printf("\n\n%d",i);
return 0;
}
But x is greater than z here so how is this happening ?
The expression x
(x < y) < z
so it becomes
(10 < 10) < 5
which further is evaluated into
0 < 5
which is true.
I think you wanted something like this:
x < y && y < z
Because of operator precedence and associativity
i = x < y < z;
is parsed as:
i = ((x < y) < z);
After substituting the variable values, this becomes:
i = ((10 < 10) < 5);
Since 10 < 10 is false, this becomes:
i = (0 < 5);
Since 0 < 5 is true, that becomes:
i = 1;
x<y<z is not a single valid expression. Instead it evaluates x<y first (operator precedence is done left to right here) as true/false (false in this case as they're equal), converts it to an int value of 0, and then compares this value with z.
Use (x < y && y < z) instead.
It first evaluates x < y which is false (0), then 0 < z which is true (1).
WHat C compiler does is, in x<y<z;
starts from left, so as x is not less than y therefore it replaces that expression with '0'
so it becomes 0<z and as that is true. it set the variable to 1.
I am beginner in C programming language, recently I have read about Logical AND && operator.
I also know that, in C programming language all non-zero values are treated as TRUE.
NON-ZERO && NON-ZERO = 1
NON-ZERO && ZERO = 0
ZERO && NON-ZERO = 0
ZERO && ZERO = 0
But when I am dealing with the following program then I am not getting expected answer.
int main(){
int x, y, z;
x = y = z = -1;
y = ++x && ++y && ++z;
printf("x = %d, y = %d, z = %d, x, y, z);
return 0;
}
I am expecting
x = 0, y = 0, z = 0
but the answer is
x = 0, y = 0, z = -1
Can anyone please explain, Why I am getting this answer?
Edit:
In this question, I have not asked about the precedence of operators.
Because of Short-circuit evaluation, when x is 0, y and z don't really need to be evaluated since 0 && ANYTHING is 0.
Once x is incremented to 0, the result is 0, and that's what y gets.
z remains unchanged (-1).
x | y | z
----+----+-----
-1 | -1 | -1 //x = y = z = -1;
0 | -1 | -1 //++x && ... Now the whole expression is evaluated to 0
0 | 0 | -1 //y = ++x && ++y && ++z;
I only can think about that && evaluates in short circuit: given A && B, if A evaluates false then B is not evaluated.
So:
X becomes 0. && ++y && ++z does not evaluates since X/0/false && ...
y=0 as assigned from y = x/0/false
z remains unmodified since ++z does not get executed.
&& operator is evaluated pairwise, therefore I'm guessing C is evaluating
((++x && ++y) && ++z)
now, ++x will return zero therefore the first && will fail as will the second one without the need to evaluate ++y or ++z.
y = 0 since that is the result of the expression.
z is not touched
What happens is that ++y and ++z are never evaluated because the first part already ensures what the new value of y will be.
The first part of your statement is ++x && ... which is equivalent to 0 && ... and then we already know that y will be 0 in the end so the rest of the statement is not executed.
if you did this:
int main(){
int x,y,z,tmp;
x = y = z = -1;
tmp = ++x && ++y && ++z;
printf("x = %d, y = %d, z = %d, tmp = %d", x,y,z, tmp);
return 0;
}
You would get x = 0, y = -1, z = -1, tmp = 0
The left evaluation is guaranteed in the C99 standard. You can find it in the section 6.5.13 Logical AND operator
Unlike the bitwise binary & 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 equal to 0, the second operand is not evaluated.
You can find more information about what is a sequence point on Wikipedia or in the Annex C of the C99 standard
For completeness (brain dump):
The term behind this sorcery is called short circuiting. Let's go over your code and then a brief blurb about why this happens. Looking at:
int main( void ) {
int x, y, z;
x = y = z = -1;
y = ++x && ++y && ++z;
printf( "x = %d, y = %d, z = %d, x, y, z );
return 0;
}
... we begin to break it down line by line. The first line:
int x, y, z;
... declares three integers, x, y and z. They are initialized to garbage values on the stack frame because there is no initialization (assignment operator). This line does not really matter, now let's look at the next one:
x = y = z = -1;
... we see that we are doing multiple assignments on the same line. Recall that the assignment operator will mutate the identifier to the left of the assignment operator (using the value to the right of the assignment operator) and return the value of x. This is known as assignment overloading. But again, this does not really matter -- the only important thing to realize is x, y and z are now all -1. Let's look at the next line:
y = ++x && ++y && ++z;
... Sorcery Yoda says. Let's add the parenthesis to make it more obvious which step is being evaluated first:
y = ( ( ++x ) && ++y && ++z );
... now looking at the inner-most parenthesis we see that it's a prefix increment of x, meaning we will increment the value of x and then return it. We note that x is originally -1 and it is now 0 after being incremented. This will resolve as follows:
y = ( 0 && ++y && ++z );
... now it's important to note that looking at our truth tables:
A | B | A && B
--------------
T | T | T
T | F | F
F | T | F
F | F | F
... for the AND logical operator we see that both F (AND) T, T (AND) F are F. The compiler realizes this and short circuits when ever it is evaluating a conjunction (AND) where a value is false -- a clever technique of optimization. It will then resolve to assigning y to be 0 (which is false). Recall that in C any non-zero value is true, only 0 is false. The line will look as follows:
y = 0;
... now looking at the next line:
printf( "x = %d, y = %d, z = %d, x, y, z );
... it should be obvious to you now that it will output x = 0, y = 0, z = -1.
I am not understanding for loop statement and expression following it. Please do help me understand.
#include<stdio.h>
int main()
{
int x = 1;
int y = 1;
for( ; y ; printf("%d %d\n",x,y))
y = x++ <= 5;
return 0;
}
And the output I got
2 1
3 1
4 1
5 1
6 1
7 0
y = x++ <= 5; ==> y = (x++ <= 5); ==> first compare x with 5 to check whether x is small then or equals to 5 or not. Result of (x++ <= 5) is either 1, 0 assigned to y,
As x becomes > 5, (x++ <= 5) becomes 0 so y = 0 and condition false and loop break,
Basically the for syntax is:
for(StartCondition; Test; PostLoopOperation) DoWhileTestPasses;
In this case:
StartCondition == None
Test == (y != 0)
PostLoopOperation == do some printing
DoWhileTestPasses == set y to zero if x > 5 otherwise to non-zero THEN increment x.
Which is all rather bad practice because it is confusing.
Would be better written as:
int x=0;
int y=0;
for(y=0; y = (x <= 6); x++)
{
printff("%d %d\n",x,y);
}
return(0);
In y = x++ <= 5;, y stores the value that is output by the condition x++ <= 5 (here x++ is post increment). If the condition is true then y = 1 else y = 0.
for( ; y ; printf("%d %d\n",x,y))
In the for loop you are printing the values of x and y after executing the for loop body.
Initialize your variables:
int x = 1; int y = 1;
There are 3 statements for the for loop: -1. Initialize, 2. Condition, 3. Iteration:increment/decrement
In your case, you did not provide the initialize condition, however, you have the part of condition and incrementation. I do not think your for loop is used in the correct way.
You should swap the part of incrementation with your body like this:
for(; y; y = x++ <= 5;)
printf("%d %d\n", x, y)
First, you check whether the condition is true or not, y is true or not. Then, you print x and y out. Then, the part of incrementation is executed, x++ <= 5 or not. The result is assigned to y. It does so until your condition is false, y == false.
NOTE: For the good programming, you should enclose your body with a curly braces.
similar to this
int x = 1;
for( int y = 1; y!=0 ; )
{
if (x++ <= 5)
{
y = 1;
}
else
{
y = 0;
}
printf("%d %d\n",x,y);
}
Perhaps this slightly transformed (but functionally equal) code will help:
int x = 1;
int y = 1;
while (y) {
y = (x <= 5);
x = x + 1;
printf("%d %d\n", x, y)
}
#include <stdio.h>
int main () {
int x, y, z;
x = y = z = 1;
++x || ++y && ++z;
printf ("x = %d\t y = %d\tz = %d\n", x, y, z);
//op : x = 2 y = 1 z = 1
//why is 'x' only incrementd?
x = y = z = -1;
++x || ++y && ++z;
printf ("x = %d\t y = %d\tz = %d\n", x, y, z);
//op : x = 0 y = 0 z = -1
//why are 'x' and 'y' incremented?
x = y = z = 1;
++x && ++y || ++z;
printf ("x = %d\t y = %d\tz = %d\n", x, y, z);
//op : x = 2 y = 2 z = 1
//why is 'x' only incrementd?
x = y = z = -1;
++x && ++y || ++z;
printf ("x = %d\t y = %d\tz = %d\n", x, y, z);
//op : x = 0 y = -1 z = 0
//why are 'x' and 'z' incremented?
//Does this incrementation depend on the value stored in the variable?
}
The reason is that && and || short circuit.
That is, once they know what the end result of the boolean expression will be, they stop evaluating.
So, if you do 1 || x++, then x will never be incremented, because any non-zero boolean value is a true value.
Likewise, if you do 0 && x++, x++ never will get executed either.
See also:
Short-circuit evaluation on Wikipedia
|| and && short-circuit. What that means is that they perform as little work as possible to return their value, only executing the right side if the left side doesn't nail the answer.
For instance:
1 || anything();
In this case, anything() will never execute, because || can simply return as soon as it evaluates the 1; no matter what anything()'s return value, the return value of || in this expression can never be 0.
Similarly:
0 && anything_else();
Here, anything_else() will never execute, because && already knows that its value can never be anything but 0.
In your examples, the ++ preincrements don't actually affect the short-circuiting, except to hide the values that the boolean short-circuit operators are actually making their decisions on.
In general the answer to your questions is that if you have the code A||B
If A evaluates to true then B is NEVER evaluated.
So in your first case if ++x is true (in your case x==2 so it is true) then the rest of the expression is never evaluated
Similarly in the second case ++x evaluates to 0 which is false thus the second art of the expression ++y must be evaluated (and this also evaluates to 0 which is false); no wis a similar manner to the || operator if the first operand of the && operator is false then there is no need to evaluate the second operand - thus the third term is never evaluated.
The same logic can be applied to the third case.
This has to do with the way c short-circuits the || and && operators.
For example, if you have A && B, the program will evaluate A. If that turns out to be false, we already know the result will be false no matter what's in B, so B is never evaluated. If you have C || D and C evaluates to true, you know the result is true no matter what's in D, so D is never evaluated.
In this code, the increments of variables are used in conjugation with expressions.
This is to avoid using if-else structure.
Here is the examples where precedence of operators are clarified:
++x || (++y && ++z);
++x || (++y && ++z);
(++x && ++y) || ++z;
(++x && ++y) || ++z;
the expressions are evaluated from left to right.
In the first example, the program already know the whole expression will yield true after ++x, and the program will not bother to evaluate the rest of the expression. C uses something called short-circuit evaluation.
In C++ or C:
True is 1 or any non-zero value
False is 0 or any negative value
These conditions are short-circuited - so when C++/C comes across the first true part - it breaks and doesn't evaluate the rest.
x = y = z = 1;
++x || ++y && ++z;
printf ("x = %d\t y = %d\tz = %d\n", x, y, z);
//op : x = 2 y = 1 z = 1
//why is 'x' only incrementd?
x is true (2) and the rest of the condition is not evaluated
x = y = z = -1;
++x || ++y && ++z;
printf ("x = %d\t y = %d\tz = %d\n", x, y, z);
//op : x = 0 y = 0 z = -1
//why are 'x' and 'y' incremented?
x is false (0) so then y is evaluated which is false (0) - since it is false it is not checked further..
x = y = z = 1;
++x && ++y || ++z;
printf ("x = %d\t y = %d\tz = %d\n", x, y, z);
//op : x = 2 y = 2 z = 1
//why is 'x' only incrementd?
x is true (2 which is non zero)
y is true (2) - since x and y are true - the first part is true so it doesnt evaluate z.
x = y = z = -1;
++x && ++y || ++z;
printf ("x = %d\t y = %d\tz = %d\n", x, y, z);
//op : x = 0 y = -1 z = 0
//why are 'x' and 'z' incremented?
it is evaluated as (x && y) || z
x is evaluated and it is false (0)
z is then evaluated and it is false(0)
the result of this condition is actually false.
I may be completely wrong but's how I understand this.
Hope it helps..