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)
?
These constructs are formally equivalent to
while (--i >= 0)
{
Body;
}
and
while (i >= 0)
{
Body;
--i;
}
Do you better see the difference?
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.
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!