【问题标题】:while(true) / while(1) vs. for(;;) [duplicate]while(true) / while(1) 与 for(;;) [重复]
【发布时间】:2012-12-13 09:05:48
【问题描述】:

可能重复:
for ( ; ; ) or while ( true ) - Which is the Correct C# Infinite Loop?
Why choosing for (;;){} over while(1)?

while(true)while(1)for(;;) 有什么区别?它们都是 C# 和 C/C++ 等语言中的无限循环。但是一个比另一个更好吗?有什么想法吗?

【问题讨论】:

标签: c# c++ c loops infinite-loop


【解决方案1】:

程序编译后就没有区别了。

以下是三个 C 程序的摘录以及所有这些程序的相应生成程序集。

让我们先试试for 循环:

#include <stdio.h>
int main(){
   for(;;)
      printf("This is a loop\n");
   return 0;
}

现在我们将尝试while 循环:

#include <stdio.h>
int main(){
   while(1)
      printf("This is a loop\n");
   return 0;
}

一个糟糕的解决方案,goto 循环:

#include <stdio.h>
int main(){
   alpha:
      printf("This is a loop\n");
      goto alpha;
   return 0;
}

现在,如果我们检查生成的程序集,使用命令gcc -S loop.c,它们看起来都像这样(我没有看到任何单独发布它们的理由,因为它们是相同的):

   .file "loop.c"
   .section .rodata
.LC0:
   .string  "This is a loop"
   .text
.globl main
   .type main, @function
main:
   leal  4(%esp), %ecx
   andl  $-16, %esp
   pushl -4(%ecx)
   pushl %ebp
   movl  %esp, %ebp
   pushl %ecx
   subl  $4, %esp
.L2:
   movl  $.LC0, (%esp)
   call  puts
   jmp   .L2
   .size main, .-main
   .ident   "GCC: (GNU) 4.2.4 (Ubuntu 4.2.4-1ubuntu4)"
   .section .note.GNU-stack,"",@progbits

这部分是循环。它声明一个标签,将地址复制到字符串到寄存器中,调用一个名为puts 的例程,然后跳回标签:

.L2:
   movl  $.LC0, (%esp)
   call  puts
   jmp   .L2

由于它们都做完全相同的事情,显然它们中的任何一个都没有技术优势(至少如果您使用的是gcc)。

但是,人们有自己的观点,并且无论出于何种原因,他们都可能偏爱其中的一个。因为for(;;) 只有七个字符,所以更容易输入(这是我的偏好)。另一方面,while(1) 给人一种测试总是评估为true 的错觉,有些人可能会觉得这更直观。只有少数疯狂的人最喜欢goto 解决方案。

编辑:显然某些编译器可能会为 while(1) 生成警告,因为条件始终为真,但此类警告很容易被禁用并且对生成的程序集没有影响。

【讨论】:

  • @Cheersandhth.-Alf 我想你说得有道理。我使用的是gcc,它不会发出此类警告。也许我会在 Visual Studio 中尝试一下。我使用生成的程序集来支持我的主张,即所有这些创建无限循环的方法都做同样的事情,因为我觉得这些主张应该有确凿的证据支持,而不是凭空捏造。
  • 我听说过编译器可能会警告 while (1) 的情况,因为条件始终为真,而不会警告 for (;;),因为没有(显式)条件。
猜你喜欢
  • 2011-04-17
  • 2011-11-23
  • 2010-10-01
  • 1970-01-01
  • 2013-03-02
  • 2011-01-16
  • 2014-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多