I have a problem with predicting result of code linked below.
Why program is printing 2 0 6 0 10 0 16 0 20 0 ? I guess it is all about operators precedence, but after thinking a while I can't realize what's wrong with my interpretation. Can you explain it a little bit?
#include <stdio.h>
int main(void)
{
int tab[10] = {2,4,6,8,10,14,16,18,20};
int *pi, i;
for(pi = tab; ++pi < tab+9;)
{
*pi++ = 0;
*pi *= 2;
}
for(int i=0; i<10; i++)
printf("%d ", tab[i]);
return 0;
}
The first thing that the for loop does is point pi at tab, i.e. pi=&tab[0]
So pi is pointing at the number 2. The next piece of code to be executed is the for loop's "condition" statement ++pi < tab+9. This first increments pi (so it's now pointing at the number 4 in tab[1]) and checks whether it's still pointing at a member of tab earlier than the final 20.
In the body of the for loop, the line *pi++ = 0; first stores a 0 at the address pointed to by pi (which means that tab[1] is now 0 rather than 4) and then (post-) increments pi to point at tab[2], which is 6. Then the line *pi *= 2; doubles the value pointed to by pi, so tab[2] becomes 12.
The next thing that happens is a re-evaluation of the for loop's conditional statement (since its iteration statement is empty): pi is incremented and checked.
The rest of the iterations are fairly uneventful. The final state of tab is that the first member is unchanged, members with an odd index are zero, and other members are doubled from their initial value.
General advice regarding operators and precedence: one of two situations is almost always the case. The first is that you and the compiler don't agree on the order in which the operators in your code will be applied—in other words your code doesn't do what you expect. The second is that you understand perfectly what the compiler is going to do, but the programmer reading your code does not—in other words your code doesn't do what they expect. Fortunately, both situations can be mitigated by adding parentheses to remove any doubt.
The actual output is 2 0 12 0 20 0 32 0 40 0 (as shown in Blastfurnace comment https://ideone.com/UUy8QO)
pi is indeed initially on the first cell, but your stop condition increment the pointer. Therefore, inside the loop, for the first instruction, pi is in tab[1]. It first put this cell to 0, then increment with ++. On the second line, it double the value, therefore it double tab[2]. Then, the stop condition again increment the pointer, and so on.
Related
The semicolon has been added after the first while loop, but why is the value of the i variable 3 here, where j is 2?
#include<stdio.h>
int main()
{
int i=1;
while(i++<=1);
printf("%d",i);
int j=1;
while(j++<=1)
printf("%d",j);
return 0;
}
Both while loops run once (and once only); the difference is that, in the second case (the j loop) you are printing the 'control variable' inside the loop but, for the first case, you are printing it after the loop condition has evaluated to false. Also note that, in the first case, the semicolon immediately following the while statement defines the body of that loop as empty1.
Let's break down the first loop into steps:
On the first test of the condition, i++ evaluates to 1 and then i is incremented – so the loop runs.
On the second test, i++ evaluates to 2 (so the loop doesn't run) but i is still (post-)incremented, leaving it with the value of 3 (as shown in the output).
The same thing happens with j in the second loop but, in that case, as previously mentioned, you are displaying the value in the body of the loop (on its only run), so you see the value after the first (post-)increment.
As noted in the comments, if you add another printf("%d", j); after the body of the loop (which, in that case, consists of a single statement), you will see that j, too, has the value 3 when that loop has finished.
1 More precisely, the semicolon (on its own) defines a null statement, which forms the body of the while loop.
It is often helpful to clarify such 'null loops' by putting the semicolon on a line by itself (some compilers, with full warnings or static analysis enabled, may even suggest you do this):
#include<stdio.h>
int main()
{
int i = 1;
while (i++ <= 1)
; // Body of loop - Null Statement
printf("%d", i); // Loop has finished
int j = 1;
while (j++ <= 1)
printf("%d", j); // Body of loop
// Loop has finished
return 0;
}
For starters let;s consider how the postfix increment operator works. From the C Standard (6.5.2.4 Postfix increment and decrement operators)
2 The result of the postfix ++ operator is the value of the
operand. As a side effect, the value of the operand object is
incremented (that is, the value 1 of the appropriate type is added to
it).
Now consider this while loop
int i=1;
while(i++<=1);
In the first iteration of the loop the value of the expression i++ as the value of its operand that is 1. So the loop will iterate a second time, Due to applying the side effect to the variable i it will be equal already to 2 when the expression i++<=1 will evaluate the second time.
Now the value of i is equal to 2 and is greater than 1. so the loop will be interrupted. Again due to applying the side effect of the postfix increment operator to the variable i it will be equal to 3. This value is outputted in the following call of printf.
In simplest terms,
consider three things for each iteration of first while loop:
first iteration:
int i = 1;//initialization
while(i++<=1); //1. i evaluated as 1,
//2. loop condition is true causing loop to iterate again.
//3. ...but not before ++ causes i==2.
second iteration:
while(i++<=1); //1. i evaluated as 2,
//2. loop condition is false causing loop to eventually exit
//3. ...but not before ++ causes i==3.
printf is not included in the while loop (because of the semicolon) but
when program flow finally reaches printf("%d",i); the value of i is output as 3
In the second loop, because printf is included in the while construct, it will output the value of j for each iteration. For the same reasons as in loop one, it will also iterate only twice, and its values at time of output will be 2 & 3.
Using a debugger to set break points, and a watch on i, you can step through code such as this to see the sequence of these effects as they happen.
For explanation porpouses look at this example:
int main()
{
int i=1;
while(i++<=1)
printf("%d",i);
printf("%d",i);
}
The Output is:
2
3
Ok let's dive into the programm procedure:
Declaring i (i = 1)
while checking Condition and it's true because i++ returns 1(old Value). That's because the ++ are after the i. If you would code it like this ++i than it returns 2(new Value) (i = 2)
execute printf (i = 2)
while checking Condition and it's false because i++ returns 2 and 2 is not <= 1 (i = 3)
execute printf (i = 3)
Do you understand?
If it solved your thoughts jumble ;) mark it as answer.
You've got many answers already so I won't try to explain it in words but with an illustration in code. I've added two functions:
One that acts like a prefix increment operator (++i)
One that acts like a postfix increment operator (i++)
I'm only using the postfix version in the program though. I've added logging to the function so you can see how it works.
#include <stdio.h>
// this acts as if you put ++ before the variable
int preinc(int* p) {
++*p;
return *p;
}
// this acts as if you put ++ after the variable
int postinc(int* p) {
int rv = *p;
++*p;
printf("returning %d but incremented to %d\n", rv, *p);
return rv;
}
int main() {
int i=1;
while(postinc(&i) <= 1);
printf("end result: %d\n---\n", i);
int j=1;
while(postinc(&j) <= 1)
printf("in loop: %d\n", j);
printf("end result: %d\n", j);
}
Output:
returning 1 but incremented to 2
returning 2 but incremented to 3
end result: 3
---
returning 1 but incremented to 2
in loop: 2
returning 2 but incremented to 3
end result: 3
If you add the semicolon in the end of the while you will take: i = 3 and j = 3(IN THE OUTPUT).
If you add the semicolon only in the end of the printf and not to the while you will take i = 2 and j = 2(IN THE OUTPUT), but in the end you will, also, have the values
i = 3 and j = 3.
This happens because the "i" variable is incremented only after the first iteration of the loop, in which the empty statement (terminated by the semicolon) is evaluated.
that is why it is highly recommended to do "++i" rather than "i++", because then the incrementation is performed prior to the evaluation.
if you flip it here, you will see that i will be equal to 2 as well, regardless of the presence of the semicolon
So, I understand that i++ increments post the condition is fulfilled, while ++i increments before the condition is fulfilled. That takes me to my question:
#include<stdio.h>
int main()
{
int i=0;
while(++i<10)
printf("%d\n",i);
return 0;
}
Now here we need the initialization of i from 0 as when it goes in the while loop, it will get incremented first, and thus it will be like while(1<10), and so it will print numbers from one to ten.
Second code:
#include<stdio.h>
int main()
{
int i=0;
while(i++<10)
printf("%d\n",i);
return 0;
}
Now since i++ increments after the value has been used, so why do we initialize i from i=0, as if it gets incremented after the comparision of value of i takes place, then why isn't 0 getting printed as well because the first loop should go like while(0<10), and not like while(1<10)? So, why is zero not getting printed?
Thank you for your time.
Yes, the first condition will evaluate to 0 < 10. You can verify that by changing it to while (i++ < 1) and see that the loop still runs (once), so clearly it's using 0 for the condition (1 < 1 would be false of course).
So why does it print 1? Because it doesn't print whichever value was used for the condition. It prints the current value of i. And the current value of i is 1 at that point because i was incremented right after it was used in the condition.
The difference of pre- and post- increment applies only to the value that the expression evaluates to.
After the evaluation of i++<10 is completed, the incrementation is also completed, and i has the value 1 in the first iteration.
printf("%d\n",i); is executed after the evaluation of i++<10, so i has the value 1 here in the first iteration.
Zero isn't printed because i is incremented right after the comparison, like this:
while(i<10) {
i += 1;
printf("%d\n",i);
}
The first sentence of your question is almost the answer:
i++ increments post the condition is fulfilled
It's incremented after the condition is checked, so i++ < 10 will increment i regardless of whether the condition ends up true or false.
The operation of ++ is not done before or after any “condition” it is in. It must be completed sometime in or around the full expression it is in. The answers that say i is updated “before” or “after” the ++i or i++ is evaluated are incorrect.
Prefix ++i does two separate things that may happen in any order:
It evaluates to the value of i after one is added.
It adds one to the stored value of i.
Postfix i++ does two separate things that may happen in any order:
It evaluates to the value of i before one is added.
It adds one to the stored value of i.
That change to the stored value of i is called a side effect. It is disconnected from the main evaluation of the expression. It can be performed before, during, or after the evaluation of i, but the evaluation still returns the pre- or post-increment value, as described above.
A full expression is one that is not contained inside another expression. So, in while (++i < 10), ++i < 10 is a full expression. The side effect can occur before any part of that is evaluated, after the value of i plus one is calculated, or after the < is evaluated. It can also occur in parts (such as updating the bytes of i one by one) during the evaluations. However, the side effect must occur after any previous full expression and before any later full expression. That is because the C standard says there is a sequence point between any two full expressions. (And there are some other rules about order of execution.)
Even if the stored value of i is updated before i++ or after ++i, the expression must still produce the value of i before or after the increment, respectively. For example, for i++, the compiler can fetch i, add one, store i, but then use the pre-add value in the expression.
The result of i++ is the value of i. As a side effect i is incremented.
The result of ++i is the value of i + 1. As a side effect i is incremented.
The statement
x = i++;
is logically equivalent to
tmp = i;
x = tmp;
i = i + 1;
with the caveat that the assignments to x and i can happen in any order, or even simultaneously (interleaved or in parallel).
Similarly, the statement
x = ++i;
is logically equivalent to
tmp = i + 1;
x = tmp;
i = i + 1;
with the same caveat as above. Again, these are logical equivalents, not what the compiler actually generates - depending on the compiler and the code involved there may not be a temporary.
In the second code, the increment will take place after the condition but before the printing statement.
Thus, the incremented value of i is printed.
This is your answer in simple language.
This question already has answers here:
What is the difference between ++i and i++?
(20 answers)
Closed 4 years ago.
I was solving some multiple choice C codes from a book. Two of the questions involve pre decrementing, post decrementing a char variable initialised at 0. The output for both these is very different. I dont understand whats going on there.
Code 1
char i=0;
do
{
printf("%d ",i);
}while(i--);
return 0;
The output for this snippet is 0.
Code 2
char i=0;
do
{
printf("%d ",i);
}while(--i);
return 0;
The output is for this one is
0,-1,-2,.....-128,127,126,......1 .
Can anyone explain why this is happening?
At both code while loop checking i==0 or not. If i!=0it will keep going on.
At first code value of i initially 0. So after printing 0 it checks i==0 or not. if i==0 it will break the loop or keep going on by decrementing i. So in code 1 post decrementing used. check value first then decrements the value.
At second code value of i initially 0. So after printing 0 it decrements i then it checks if i==0 or not. it is pre decrement. decrement value first then check.
Here, i is char which size is 1 byte and range -128 to 127. So after decrementing value 0 to -1 it keep decrementing until it goes to 0 and exit the loop by printing 0,-1,...,-128,127...1 .
Code 1
char i=0;
do
{
printf("%d ",i); // print o
}while(i--); //check i = 0, means false, loop ends, then increment i
return 0;
Code 2
char i=0;
do
{
printf("%d ",i); //print 0
}while(--i); //decrement i, check i=-1, means true, next cycle, loop until i = 0 which means false
return 0;
Both i-- and --i are expressions. An expression is (part of) a statement that can yield a value. As per definition, the pre-increment version increments first, then yields the value. For the post-increment version it is the other way round.
This is completely independent of whether the expression is used in a while statement or elsewhere. However, when using such expressions, you need to be aware of operator precendence.
Initial value of i is 0.
In Code 1, first while check happens in which the value of i (= 0) is used and then i is decremented because it is postfix decrement. So it exits while after printing 0.
In Code 2, because it is prefix decrement, i is decremented first and its value (= -1) is used when the while check is performed. Here it exits after printing the entire range of values a signed char can hold because it becomes 0 at the end only.
#include <stdio.h>
int main()
{
int i=0;
while(i++,i<=8);
printf("%d\n",i);
return 0;
}
Why is the increment of i done after the comparison in each test case?
i <= 8 succeeds for the last time when i = 8.
In the last iteration, i++ is executed, then i <= 8 fails because i = 9.
Note that the , is a sequence point, so i++ is absolutely guaranteed to be executed before i <= 8. Not so for similar constructs.
It's not. Your loop condition is i <= 8, it is first non-true when i reaches 9 (you're incrementing i by 1 each time, so it will be exactly 9). That is why it prints 9.
To reach to the print() statement, while loop must end. The terminating condition, controlling expression should evaluate to false (or, in other words, until the controlling expression compares equal to 0), i.e., it will be false only when i <= 8; evaluates to false. For a value of i as 9, that happens.
Next line, the value of i, gets printed. So, you see 9.
Increment of i is not done after the comparison in each test case. i++ is executed first and after that the comparison is done.
This is because when expressions are separated using commas in C, the expressions are evaluated from left to right and the value of the last expression becomes the value of the total comma separated expression.
So the value of
i++,i<=8
is actually the value of i<=8 and that comparison is done only after i++ is executed.
So the while loop here
int i=0;
while(i++,i<=8);
is equivalent to
for(i=1; i<=8; i++);
Hence the control exits the loop only when i is greater than 8. Since i is incremented by 1 on each iteration, this means that the loop is over when i becomes 9.
You started i = 0 and using while ( i++, i<=8 ) loop you incremented it's value until 8 and when it's increased one more time i = 9 , then loop condition became false and breaks the loop with i = 9. And that's why now, when you print i's value, it gave you 9.
can anyone explain the working of the for loop in the following code:
#include<stdio.h>
#include<conio.h>
int main()
{
char i=0;
for(i<=5&&i>=-1;++i;i>0)
printf("%d\n",i);
getch();
}
Let's break the for statement down, we have three phases, the initialiser, the test, and the modifier:
for(<Initialiser>; <Test>; <Modifier>)
<content>;
In your case:
for(i<=5&&i>=-1;++i;i>0)
// initialiser: i<=5&&i>=-1;
// test: ++i;
// modifier: i>0
The initialiser is done first. Here no assignment is done. Two boolean expressions (denoted by the >= and <= operators are compared in a logical &&. The whole initialiser returns a boolean value but it doesn't do anything. It could be left as a blank ; and there would be no change.
The test uses the pre-increment operator and so returns the result of i+1. If this result is ever 0 it evaluates as false and the loop will terminate. For any non-zero value it evaluates to true and continues. This is often used when i is initialised to a value less than zero and so the test will increment i until i+1 results in a zero, at which point the loop terminates.
Finally we have the modifier, which in this case simply uses the > operator to evaluate to a boolean value. No assignment is done here either.
The fact is that you've gotten the test and the modifier confused and put them in the wrong positions but before we sort that out let's see how it would work…
We begin with:
char i = 0;
…and for all intents and purposes this does the same thing as our for loops initialiser would do in normal circumstances. The next thing to be evaluated is the for loop's initialiser:
i<=5 && i>=-1;
Because i is 0 it is less-than-or-equal-to 5 and it is greater-than-or-equal-to -1. This expression evaluates to 1 but nothing is done with that value. All we've done is waste a bit of time with an evaluation.
Next up is the modifier to test whether or not the for loop's inner block should be executed:
++i;
This evaluates to 1 and also assigns that value to i. Now, as it's evaluated to a non-zero number, the loop executes:
printf("%d\n",i);
And the digit 1 is printed to the screen... Now it's the modifier that gets executed:
i>0
Well, i is 1 so that is greater-than 0. This evaluates to 1 (or true). Either way, this is ignored. The purpose of the modifier isn't to test or check anything. It's there so that you can change the state of the program each time the for loop iterates. Either way, the loop repeats and it will do this for a very long time. Why? Because ++i is going to evaluate to a non-zero number for a while. Whether or not it will ever terminate depends on how your system deals with integer overflows.
This is what you meant to do:
#include<stdio.h>
#include<conio.h>
int main()
{
for(char i=0; i<=5&&i>=-1; ++i)
printf("%d\n",i);
}
Do you see the difference? Our initialiser now starts the loop with the state of i as zero. We then test if it's within the bounds of -1 to 5 and each time we iterate we increment i by 1. This loop will output:
0
1
2
3
4
5
This snippet:
for(i<=5&&i>=-1;++i;i>0)
printf("%d\n",i);
Does the same as this:
i<=5 && i>=-1; //statement with no effect
while(++i)
{
printf("%d\n",i);
i>0; //statement with no effect
}
So, it's going to print i until ++i evaluates to 0. This will happen after i overflows and becomes negative, then incrementing towards 0. That will take 255 iterations to happen, since chars can store up to 256 different values.
for ( variable initialization; condition; variable update ) {
}
the variable initialization phase is done only once when the for loop starts.
the condition is checked everytime before running code inside the loop. if the condition is false then the loop is exited.
the variable update is done after the first iteration, from the second iteration it is done before the condition check.