37

When implementing an infinite loop, is there a difference in using while(1) vs for(;;) vs goto?

Thanks, Chenz

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
Crazy Chenz
  • 12,650
  • 12
  • 50
  • 62
  • 1
    I always use while. I see no point in a for loop constructed in such a way. That's just a personal preference. (It appears to me to be missing information, while the while loop looks (to me) more aesthetically pleasing) – Tim Feb 18 '10 at 13:26
  • technically, the 1 in the while is a condition which should be tested at each iteration. I do believe all common compilers are smart enough to make a jump out of that one that, rather than a conditional one. Aside from that, they're all equivalent except for style. – falstro Feb 18 '10 at 13:30
  • 3
    Which infinite loop is faster than the other ? – Anonym Feb 18 '10 at 13:31
  • 3
    Dupe http://stackoverflow.com/questions/2242646/loops-in-c-for-or-while-which-is-best –  Feb 18 '10 at 13:32
  • 14
    Using `for(;;)` allows you to `#define ever (;;)` and use `for ever {...` ;) – kennytm Feb 18 '10 at 13:39
  • +1 for KennyTM for this great #define – tur1ng Feb 18 '10 at 14:16
  • nitpick for @Neil: this is a semi-dupe. The question you linked talks about `while()` and `for()` in general. This question's about infinite loops. – tomlogic Feb 19 '10 at 02:20
  • 2
    @KennyTM: This is funny and on the other hand misleading. Usually a "infinite" loop doesn't actually last forever but until it is "break"-ed. – chiccodoro Aug 06 '10 at 15:55
  • @chiccodoro `#define indefinitely for(;;)` `indefinitely {}` – Andrew May 27 '21 at 05:58

8 Answers8

60

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
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • 4
    What command was used to produce this specific assembly output from the object file? – bzeaman May 25 '16 at 09:15
  • @bzeaman See my answer [here](https://stackoverflow.com/a/67717002/1599699) for more information on how to do this for g++ and clang++ and how to add comments so that you know which part of the assembly to look at... – Andrew May 27 '21 at 06:50
9

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.

Otto Allmendinger
  • 27,448
  • 7
  • 68
  • 79
5

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...

MaR
  • 829
  • 4
  • 7
4

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).

DrAl
  • 70,428
  • 10
  • 106
  • 108
4

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.

Danilo Piazzalunga
  • 7,590
  • 5
  • 49
  • 75
3

None. Use what is the most readable to you

MrValdez
  • 8,515
  • 10
  • 56
  • 79
2

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.

Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
0

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.

jldupont
  • 93,734
  • 56
  • 203
  • 318