What does for (; --i >= 0; ) mean in C?
How is the counter getting decremented and how is it different from for ( ; i >= 0; --i)?
What does for (; --i >= 0; ) mean in C?
How is the counter getting decremented and how is it different from for ( ; i >= 0; --i)?
They are very similar, but not the same! First you have to understand how a for loop in C gets executed:
As an example:
1 2, 5 4
| | |
v v v
for(i = 0; i < 5; i++) {
// Do something <-- 3
}
As you can see 2, 3, 4, 5 is a loop until the condition is false.
Now you should clearly see how the for loop gets executed. The difference now is that in your first example:
int i = 5;
for ( ; --i >= 0; )
printf("%d\n", i);
The output would be:
4
3
2
1
0
Because after the first check of the condition (Point 2), it executes the code block of the for statement and i already gets decremented.
In your second example:
int i = 5;
for( ; i>=0; --i)
printf("%d\n", i);
The output would be:
5 // See here the difference
4
3
2
1
0
Here you get the difference, because it gets decremented in Point 4, so the first time it runs with the value 5.
These constructs are formally equivalent to
while (--i >= 0)
{
Body;
}
and
while (i >= 0)
{
Body;
--i;
}
Do you better see the difference?
In general, we can convert any for loop or while loop into a set of mostly linear statements with a goto. Doing this may be helpful to compare the code.
### for (; --i >= 0; ) { statements; }
; // Initializer statement
start:
bool condition = (--i >= 0); // Conditional
if (condition) { // If true, we execute the body as so:
statements; // The statements inside the loop
; // Empty increment statement
goto start // Go to the top of the loop.
}
### for( ; i>=0; --i) { statements; }
; // Initializer statement
start:
bool condition = (i >= 0); // Conditional
if (condition) { // If true, we execute the body as so:
statements; // The statements inside the loop
--i; // Increment statement
goto start; // Go to the top of the loop.
}
In the first case, we decrement i for the first time before each loop body. In the second case, we decrement i after each loop body.
The easiest way to see that is to consider what happens when you enter this loop when i == 0. In the first case, after this block of code, you would have a resulting value of i == -1. In the second case, i wouldn't have changed (that is, i == 0), because we never reached the increment statement.
for (; --i >= 0; ) works like this:
Say if you have i as 10, it will decrement the i value and will compare 9 >= 0 and so on.
So the output would be like 9, 8... till 0.
While the loop for( ; i>=0;--i) would first go to 10, then decrement the value and then it would check i>=0. So the output would be 10, 9, 8... till 0.
The first one decrements i and then checks the condition.
The second one checks the condition first and if true, decrements i after the loop body has been executed.
The three parameters (initialization, condition and increment) in for are optional (but they still requires the semicolon ;). So, you can safely write for(;;) and it's the same as while(1). So, expressions like
for(; x > y; x++) { ... }
for(;1;x++) { if(x > y) break;
for(;;) { if(x++ > y) break;
for(;x++ > y;) { ... }
Are valid and equivalent. In this, the increment occurs in the conditional parameters, just like in your code example.
Well, it is the same as saying for( i=0 or some value; --i <= 0 ; do nothing){}
and --i is an predecrement operator.
That means when this piece of code, i.e., --i, is being read, the value of i will decrease by 1 at the same moment.
There are three main components in a for loop.
Initialization, condition, and afterthought.
Initialization happens once at the start of the entire statement. Condition happens before every cycle. Afterthought comes after every cycle. Consider i starts at 2:
for (; --i >= 0; )
Initialization: i = 2
Condition: i = 1
Afterthought: i = 1
Condition: i = 0
Afterthought: i = 0
Condition: i = -1
Exit
In the other case
for( ; i>=0; --i)
Initialization: i = 2
Condition: i = 2
Afterthought: i = 1
Condition: i = 1
Afterthought: i = 0
Condition: i = 0
Afterthought: i = -1
Condition: i = -1
Exit
You can see that the second version actually lasts one cycle longer!