When implementing an infinite loop, is there a difference in using while(1)
vs for(;;)
vs goto
?
Thanks, Chenz
When implementing an infinite loop, is there a difference in using while(1)
vs for(;;)
vs goto
?
Thanks, Chenz
From what I recall of my "disassembling years", it won't make much a difference (compilers are smart enough). It is more about aesthetics IMO.
In C, true
is implemented as follows (depending on compiler)
#define TRUE 1
or
#define TRUE (-1)
AND false is implemented as
#define FALSE 0
so while (1)
is equivalent to while (true)
since 0 is considered false.
the while (1) == for (; ;)
as there are no stopping condition.
which is translated to assembler as
:loop
...
...
...
goto loop
so if the assembler code doesn't have a ret
or exit
instruction, it's considered a infinite loop.
They are equivalent, even if you turn the optimizer off.
Example:
#include <stdio.h>
extern void f(void) {
while(1) {
putchar(' ');
}
}
extern void g(void) {
for(;;){
putchar(' ');
}
}
extern void h(void) {
z:
putchar(' ');
goto z;
}
Compile with gcc -O0
gives equivalent assembly for all 3 functions:
f:
; [ EXTERNAL ]
;
+00000 00000fb4 80402DE9 stmdb sp!,{r7,lr}
+00004 00000fb8 00708DE2 add r7,sp,#0x0
+00008 00000fbc 2000A0E3 loc_000008: mov r0,#0x20
+0000c 00000fc0 0A0000EB bl putchar (stub)
+00010 00000fc4 FCFFFFEA b loc_000008
;
;
g:
; [ EXTERNAL ]
;
+00000 00000fc8 80402DE9 stmdb sp!,{r7,lr}
+00004 00000fcc 00708DE2 add r7,sp,#0x0
+00008 00000fd0 2000A0E3 loc_000008: mov r0,#0x20
+0000c 00000fd4 050000EB bl putchar (stub)
+00010 00000fd8 FCFFFFEA b loc_000008
;
;
h:
; [ EXTERNAL ]
;
+00000 00000fdc 80402DE9 stmdb sp!,{r7,lr}
+00004 00000fe0 00708DE2 add r7,sp,#0x0
+00008 00000fe4 2000A0E3 loc_000008: mov r0,#0x20
+0000c 00000fe8 000000EB bl putchar (stub)
+00010 00000fec FCFFFFEA b loc_000008
I just compared the unoptimized assembler output of gcc:
# cat while.c
int main() {
while(1) {};
return 0;
}
# cat forloop.c
int main() {
for (;;) { };
return 0;
}
Make assembler output:
# gcc -S while.c
# gcc -S forloop.c
Compare assembler files:
# diff forloop.s while.s
1c1
< .file "forloop.c"
---
> .file "while.c"
As you can see there are no significant differences. Here is the output
# cat while.s
.file "while.c"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
.L2:
jmp .L2 # this is the loop in both cases
.size main, .-main
.ident "GCC: (GNU) 4.4.3"
.section .note.GNU-stack,"",@progbits
While this is not a technical proof that they are the same, I'd say it is in 99.9% of the cases.
There is hardly any difference in generated assembly. It's more of an stylistic issue:
Goto - just ooogly: jumps backward, no explicit infinite block
while(1) - better, requires "dummy" condition though and you'll be often warned by compiler(warning level 4) or static analysis tool
for(;;) might not be the prettiest, but imho fits best because this construct cannot have any other meaning (compared to while). But some other people prefer while(1) for the "same" reason...
Although there's no significant difference as mentioned in the other posts, a common reason to use for (;;)
instead of while (1)
is that static analysis tools (and some compilers with certain warning levels) often complain about the while loop.
Goto is a bit nasty, but should produce the same code as the others. Personally, I stick to for (;;)
(to keep Lint happy), but I have no problem with while (1)
.
while(1)
and for(;;)
are exactly equivalent and both are well-understood idioms to code infinite loops.
I would avoid the use of goto
: to break from an infinite loop or to proceed to the next iteration, use break
and continue
.