在实现无限循环时,使用while(1)vs for(;;)vs goto(在C中)是否存在差异?

时间:2010-02-18 13:24:55

标签: c loops for-loop goto while-loop

实施无限循环时,使用while(1) vs for(;;) vs goto会有区别吗?

谢谢, Chenz

8 个答案:

答案 0 :(得分:51)

即使关闭优化器,它们也是等效的。

示例:

#include <stdio.h>

extern void f(void) {
    while(1) {
        putchar(' ');
    }
}

extern void g(void) {
    for(;;){
        putchar(' ');
    }
}

extern void h(void) {
    z:
        putchar(' ');
    goto z;
}

使用gcc -O0编译为所有3个函数提供等效的程序集:

 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

答案 1 :(得分:7)

我刚刚比较了gcc的未经优化的汇编程序输出:

# cat while.c 
int main() {
    while(1) {};
    return 0;
}

# cat forloop.c 
int main() {
    for (;;) { };
    return 0;
}

make汇编输出:

# gcc -S while.c 
# gcc -S forloop.c 

比较汇编程序文件:

# diff forloop.s while.s
1c1
<   .file   "forloop.c"
---
>   .file   "while.c"

如您所见,没有显着差异。这是输出

# 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

虽然这不是技术证明它们是相同的,但我认为它占99.9%。

答案 2 :(得分:4)

生成的组件几乎没有任何差异。这更像是一个风格问题:

转到 - 只是ooogly:向后跳,没有明确的无限阻挡

虽然(1) - 更好,但需要“虚拟”条件,并且您经常会被编译器(警告级别4)或静态分析工具警告

对于(;;)的

可能不是最漂亮的,但imho非常适合,因为此构造不具有任何其他含义(与while相比)。但是其他一些人更喜欢(1)因为“相同”的原因......

答案 3 :(得分:4)

while(1)for(;;)完全等效,两者都是用于编码无限循环的易于理解的习惯用法。

我会避免使用goto:打破无限循环或继续下一次迭代,使用breakcontinue

答案 4 :(得分:3)

无。使用最易读的内容

答案 5 :(得分:3)

虽然其他帖子中没有显着差异,但使用for (;;)代替while (1)的常见原因是静态分析工具(以及某些具有某些警告级别的编译器)经常抱怨while loop。

Goto有点讨厌,但应该生成与其他代码相同的代码。就个人而言,我坚持for (;;)(让Lint高兴),但while (1)没问题。

答案 6 :(得分:2)

在C中,true实现如下(取决于编译器)

#define TRUE 1

#define TRUE (-1)

AND false实现为

#define FALSE 0

所以while (1)相当于while (true),因为0被认为是假的。

while (1) == for (; ;)因为没有停止条件。

将其翻译为汇编程序

:loop
  ...
  ...
  ...
  goto loop

因此,如果汇编程序代码没有retexit指令,则认为它是无限循环。

答案 7 :(得分:0)

从我记得的“拆解年代”来看,它不会产生太大的影响(编译器智能就足够了)。它更多的是关于美学IMO。