实现无限循环时,使用 while(1) 与 for(;;) 与 goto (在 C 中)有区别吗?

发布于 2024-08-21 20:37:27 字数 103 浏览 11 评论 0原文

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

谢谢, 陈兹

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

Thanks,
Chenz

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

夏末 2024-08-28 20:37:28

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

示例:

#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

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
霊感 2024-08-28 20:37:28

我只是比较了 gcc 未优化的汇编器输出:

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

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

生成汇编器输出:

# 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% 的情况下都是相同的。

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.

看春风乍起 2024-08-28 20:37:28

生成的程序集几乎没有任何区别。这更多的是一个风格问题:

Goto - 只是 ooogly:向后跳转,没有明确的无限块

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

for(;;) 可能不是最漂亮的,但恕我直言,最适合,因为这个构造不能有任何其他含义(与 while 相比)。但其他一些人出于“相同”的原因更喜欢 while(1) ......

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

晨光如昨 2024-08-28 20:37:28

尽管没有其他帖子中提到的显着差异,但使用 for (;;) 而不是 while (1) 的一个常见原因是静态分析工具(以及一些具有某些警告级别的编译器)经常抱怨 while 循环。

Goto 有点令人讨厌,但应该生成与其他代码相同的代码。就我个人而言,我坚持使用 for (;;) (让 Lint 满意),但我对 while (1) 没有任何问题。

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

冬天旳寂寞 2024-08-28 20:37:28

while(1)for(;;) 完全相同,并且都是易于理解的无限循环代码习惯用法。

我会避免使用 goto:要从无限循环中中断或继续下一次迭代,请使用 breakcontinue

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.

卷耳 2024-08-28 20:37:28

没有任何。使用对您来说最易读的内容

None. Use what is the most readable to you

一身软味 2024-08-28 20:37:28

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

#define TRUE 1

#define TRUE (-1)

AND false 实现如下

#define FALSE 0

while (1) 相当于 while (true) 因为 0 被认为是 false。

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

它被翻译为汇编程序,因此

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

如果汇编程序代码没有 retexit 指令,则被视为无限循环。

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.

下壹個目標 2024-08-28 20:37:28

从我对我的“反汇编岁月”的回忆来看,这不会产生太大的影响(编译器聪明足够)。在我看来,这更多的是关于美学。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文