1. ## Loop syntax battle!

Today, I have a collection of simple incremental loops to generate numbers between 0 to 9.

A. "for" statement

1. A common way to make a loop
Code:
```for(i=0; i<10; i++)
{
printf("%d", i);
}```
2. Strip the initialization
Code:
```i = 0;

for(;i<10; i++)
{
printf("%d", i);
}```
3. Use ++ inside conditional statement
Code:
```i = 0;

for( ; i++<10; )
{
printf("%d", (i - 1));
}```
4. Use ++ inside the loop
Code:
```i = 0;

for( ; i<10; )
{
printf("%d", i++);
}```

B. "while" statement

1.
Code:
```i = 0;

while(i<10)
{
printf("%d", i);
i++;
}```
2.
Code:
```i = 0;

while(i++<10)
{
printf("%d", (i - 1));
}```
3.
Code:
```i = 0;

while(i<10)
{
printf("%d", i++);
}```

C. "do-while" statement

1.
Code:
```i = 0;

do
{
printf("%d", i);
i++;
}
while(i<10);```
2.
Code:
```i = 0;

do
{
printf("%d", i);
}
while(++i<10);```
3.
Code:
```i = 0;

do
{
printf("%d", i++);
}
while(i<10);```

D. linear style

1.
Code:
```i = 0;

loop:

printf("%d", i);
i++;

if(i<10)
goto loop;```
2.
Code:
```i = 0;

loop2:

printf("%d", i);

if(++i<10)
goto loop2;```
3.
Code:
```i = 0;

loop3:

printf("%d", i++);

if(i<10)
goto loop3;```

Which is nicest syntax for you? Why?
Would you like to guess which is (type and run)faster after all?

2. Use for/next when the exact number of iterations is known in advance.

Use while loop when the loop *may* not be entered into at all, and you need to test this before entering even the first loop iteration, and the exact number of iterations to be done is not known.

Use do/while when the loop *must* be entered into and one iteration done, but the exact number of iterations is not known.

Forget the rest, they're dumb.

3. Forget the rest, they're dumb.
Do you mean linear style? Why dumb???

4. Because goto is hated since it can jump all over the code and create mess.
Stay away from goto.

5. When there is a better standard loop style, it should be used. The "linear style" was needed in languages way back when the modern and standard loops of today, didn't exist.

But no more. Goto's are unneeded except to escape from inside multiple loops and a few other rare situations.

Don't use goto's otherwise, and that includes the "linear style" of looping. It looks like BASIC, from 20 years ago. I couldn't abide that style on any program, period.

6. How about the second question?

7. The first one is the best for me.
Using ++ inside a conditional statement, or inside printf, might cause confusion, since it might not be that clear in a big code.
Using for is preferred when the number of iterations are known.
Initializing i makes the for loop more readable, since you don't have to search where i was initialized.

The first one is like the "standard" way to do it. Since the example is very simple, standard methods would look nicer. Give us a more complicated example!

8. Originally Posted by audinue
I suppose you could do it in an inefficient and limited way like this:

Code:
```void DoCount(int start, int end)
{
if(start < end)
{
printf("&#37;i\n", start);
DoCount(start + 1, end);
}
}

int main()
{
DoCount(0, 10);
return 0;
}```

9. Using inline assembly wouldn't make it "nicer". Probably neither faster, since it is too simple not to be optimized by the compiler.
Though assembly code could be used if somebody wanted to use it.

EDIT: Or for optimal results (:P)
Code:
```printf("1");
printf("2");
printf("3");
printf("4");
printf("5");
printf("6");
printf("7");
printf("8");
printf("9");
printf("10");```

10. The common way is the best, nothing worse when someone tries to be smart and "invent" their own loop.

Code:
```i = 0;
for(;;)
{
if(i >= 10)
break;

++i;
}```
just because they can...

11. Have you actually studied the difference in the code generated by the compile for those different bits of code?

Using the two most extremely different cases in GCC as this:
Code:
```#include <stdio.h>

int main()
{
int i;
#ifdef ALT1
for(i=0; i<10; i++)
{
printf("%d", i);
}
#endif

#ifdef ALT2
i = 0;

loop3:

printf("%d", i++);

if(i<10)
goto loop3;
#endif

return 0;
}```
we get from gcc -O2 -S and diff the two ALTx solutions:
Code:
```*** a_alt1.s    2008-07-16 11:02:58.640347100 +0100
--- a_alt2.s    2008-07-16 11:02:32.728512500 +0100
***************
*** 18,30 ****
call    ___main
xorl    %ebx, %ebx
.p2align 4,,15
! L5:
movl    %ebx, 4(%esp)
incl    %ebx
movl    \$LC0, (%esp)
call    _printf
cmpl    \$9, %ebx
!       jle     L5
movl    -4(%ebp), %ebx
xorl    %eax, %eax
leave
--- 18,30 ----
call    ___main
xorl    %ebx, %ebx
.p2align 4,,15
! L2:
movl    %ebx, 4(%esp)
incl    %ebx
movl    \$LC0, (%esp)
call    _printf
cmpl    \$9, %ebx
!       jle     L2
movl    -4(%ebp), %ebx
xorl    %eax, %eax
leave```
So the only difference is that the label has a different name.

--
Mats

12. Originally Posted by zacs7
The common way is the best, nothing worse when someone tries to be smart and "invent" their own loop.

Code:
```i = 0;
for(;;)
{
if(i >= 10)
break;

++i;
}```
just because they can...
And the likely scenario is that the compiler is better at optimizing the "basic" or "traditional" loop setup, and thus any deviance from the loop construction will reduce the chances of getting good code out of the compiler.

Keep it simple and stupid, and let the compiler vendor worry about how to do things.

By the way, I'd say it's fine to use a loop where the number of iterations are varaible. The condition for using a for-loop vs. while-loop is that a for-loop has the same initialization for all loops, a contion, and a proceed to next step. For example, a for-loop can be used to traverse a linked list:
Code:
```   node *p;
for(p = head; p != NULL; p = p->next) ...```
But if something doesn't quite fit in a for-loop (e.g. there's no initialization or no proceed to next portions), then you PROBABLY should use a while-loop (or do-while, if you should always perform the loop at least once).

--
Mats

13. Originally Posted by 39ster
I suppose you could do it in an inefficient and limited way like this:

Code:
```void DoCount(int start, int end)
{
if(start < end)
{
printf("%i\n", start);
DoCount(start + 1, end);
}
}

int main()
{
DoCount(0, 10);
return 0;
}```
Psstt... that's a recursion not iteration (loop)...

14. It's still a loop anyway

15. Originally Posted by audinue
Psstt... that's a recursion not iteration (loop)...
gcc actually understands that the tail recursion means the same thing as a traditional loop in this case, and generates code that just loops around like a for-loop, rather than recursion.

I couldn't make the compiler inline DoCount, otherwise, I'd expect it to be very marginally different from the original code posted - after some further playing around, it appears that the problem is that it FIRST decides whether to inline the function or not, then decides to resolve the recursion as a loop.

--
Mats