可能重复:
for ( ; ; ) 或 while ( true ) - 哪个是正确的 C# 无限循环?
为什么选择 for (;;){} 而不是 while(1)?
while(true)
,while(1)
和 和有什么区别for(;;)
?它们都是 C# 和 C/C++ 等语言中的无限循环。但是一个比另一个更好吗?有任何想法吗?
可能重复:
for ( ; ; ) 或 while ( true ) - 哪个是正确的 C# 无限循环?
为什么选择 for (;;){} 而不是 while(1)?
while(true)
,while(1)
和 和有什么区别for(;;)
?它们都是 C# 和 C/C++ 等语言中的无限循环。但是一个比另一个更好吗?有任何想法吗?
程序编译后就没有区别了。
以下是三个 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)
因为条件始终为真,但可以轻松禁用此类警告并且对生成的程序集没有影响。