for (;;) {
//Something to be done repeatedly
}
我见过这种事情很多,但我觉得这很奇怪......
说while(true)
或类似的东西不是更清楚吗?
我猜这(因为许多程序员采用神秘的代码的原因)这是一个很小的利润吗?
为什么,真的值得吗?如果是这样,为什么不这样定义:
#define while(true) for(;;)
答案 0 :(得分:252)
答案 1 :(得分:165)
我更喜欢for(;;)
,原因有两个。
一个是一些编译器在while(true)
上产生警告(类似“循环条件不变”)。避免警告总是一件好事。
另一个是我认为for(;;)
更清晰,更有说服力。
我想要一个无限循环。字面意思 没有条件,它什么都不依赖。我只是想让它永远持续下去,直到我做一些事情来摆脱它。
然而,while(true)
,那么,什么是真的与任何事情有关?我对循环不感兴趣,直到true变为false,这就是这个形式的字面意思(循环,而true为真)。我只是想循环。
不,绝对没有性能差异。
答案 2 :(得分:55)
我个人使用for (;;)
,因为其中没有任何数字,它只是一个关键字。我更喜欢while (true)
,while (1)
,while (42)
,while (!0)
等等。
答案 3 :(得分:48)
由于Dennis Ritchie
我开始使用for (;;)
,因为这就是Dennis Ritchie在K& R中的表现方式,在学习新语言时,我总是试图模仿聪明人。
这是惯用的C / C ++。如果你打算在C / C ++空间做很多事情,那么从长远来看,习惯它可能会更好。
您的#define
将无效,因为#define'd必须看起来像C标识符。
所有现代编译器都会为这两个构造生成相同的代码。
答案 4 :(得分:46)
在任何理智的编译器中肯定不会更快。它们都将编译成无条件跳转。 for版本更容易输入(如Neil所说),如果您理解循环语法,则会很清楚。
如果你很好奇,这就是gcc 4.4.1为x86提供的内容。两者都使用x86 JMP指令。
void while_infinite()
{
while(1)
{
puts("while");
}
}
void for_infinite()
{
for(;;)
{
puts("for");
}
}
汇编到(部分):
.LC0:
.string "while"
.text
.globl while_infinite
.type while_infinite, @function
while_infinite:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
.L2:
movl $.LC0, (%esp)
call puts
jmp .L2
.size while_infinite, .-while_infinite
.section .rodata
.LC1:
.string "for"
.text
.globl for_infinite
.type for_infinite, @function
for_infinite:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
.L5:
movl $.LC1, (%esp)
call puts
jmp .L5
.size for_infinite, .-for_infinite
答案 5 :(得分:41)
我更喜欢for (;;)
,因为它在不同的C语言中最为一致。
在C ++中while (true)
很好,但在C中你依赖于标题来定义true
,但TRUE
也是一个常用的宏。如果你使用while (1)
它在C和C ++和JavaScript中是正确的,而不是Java或C#,它要求循环条件是布尔值,例如while (true)
或while (1 == 1)
。在PHP中,关键字不区分大小写,但语言更喜欢大写TRUE
。
但是,for (;;)
在所有这些语言中始终完全正确。
答案 6 :(得分:21)
我个人更喜欢for (;;)
成语(它将编译为与while (TRUE)
相同的代码。
在某种意义上,使用while (TRUE)
可能更具可读性,我决定使用for (;;)
成语,因为它突出。
应该很容易在代码中注意到或调出无限循环结构,我个人认为for (;;)
样式比while (TRUE)
或while (1)
更好。
另外,我记得当while循环的控制表达式是常量时,一些编译器会发出警告。我不认为这种情况发生太多,但只是虚假警告的可能性足以让我想避免它。
答案 7 :(得分:17)
我见过有些人喜欢它,因为他们在某个地方有#define:
#define EVER ;;
允许他们写这个:
for (EVER)
{
/* blah */
}
答案 8 :(得分:16)
如果(如果您的语言支持):
start:
/* BLAH */
goto start;
答案 9 :(得分:12)
生成的机器代码没有区别。
然而,只是为了逆转这种趋势,我认为while(TRUE)形式比(;;)更具可读性和直观性,而且可读性和清晰度是编码指南的重要原因。我听说for((;)方法的原因(我更喜欢将我的编码指南建立在可靠的推理和/或有效性证明的基础上)。
答案 10 :(得分:11)
while(true)
使用Visual Studio生成警告(条件是常量)。我工作过的大多数地方编译生产版本都会将警告视为错误。所以
for(;;)
是首选。
答案 11 :(得分:11)
不仅仅是一个众所周知的模式,而是C(和C ++)中的标准习语
答案 12 :(得分:11)
如果您的代码由编译器优化,则两者应该相同。为了解释我的优化意义,这里是一个用MSVC 10编写的示例代码:
int x = 0;
while(true) // for(;;)
{
x +=1;
printf("%d", x);
}
如果您在调试模式下构建它(没有任何优化(/ Od)),反汇编会显示明显的区别。 true
内有while
条件的额外说明。
while(true)
00D313A5 mov eax,1 //extra
00D313AA test eax,eax //extra
00D313AC je main+39h (0D313B9h) //extra
{
x +=1;
00D313AE mov eax,dword ptr [x]
00D313B1 add eax,1
00D313B4 mov dword ptr [x],eax
printf("%d", x);
...
}
00D313B7 jmp main+25h (0D313A5h)
for(;;)
{
x +=1;
00D213A5 mov eax,dword ptr [x]
00D213A8 add eax,1
00D213AB mov dword ptr [x],eax
printf("%d", x);
...
}
00D213AE jmp main+25h (0D213A5h)
但是,如果您在发布模式下构建代码(默认最大化速度(/ O2)),则两者的输出都相同。两个循环都缩减为一个跳转指令。
for(;;)
{
x +=1;
01291010 inc esi
printf("%d", x);
...
}
0129101C jmp main+10h (1291010h)
while(true)
{
x +=1;
00311010 inc esi
printf("%d", x);
...
}
0031101C jmp main+10h (311010h)
无论您使用哪个,对于具有速度优化的合适编译器都无关紧要。
答案 13 :(得分:9)
这是个人偏好的问题,哪种方式更快。就个人而言,在编程期间,我是一个触摸键盘,从不看我的键盘 - 我可以触摸键盘上的所有104个键。
我发现如果更快输入“while(TRUE)”。
我精神上添加了一些手指移动测量并将它们总计。 “for(;;)”有大约12个键宽度的后退和第四个(主键和键之间,以及主键和SHIFT键之间) “while(TRUE)”有大约14个键宽度的后移和第四个。
然而,在输入后者时,我很容易出错。我一次用心语思考,所以我发现输入像“nIndex”这样的东西比“nIdx”这样的首字母缩略词更快,因为我必须精神拼出拼写而不是在脑海里说出来让我的手指自动 - 这个词(喜欢骑自行车)
(我的TypingTest.com基准= 136 WPM)
答案 14 :(得分:6)
所有好的答案 - 行为应该完全相同。
但是 - 假设它有所作为。假设其中一个每次迭代需要3个指令。
你在乎吗?
只有你在循环中做的事情几乎没有,几乎从不的情况。
我的观点是,有微优化和宏优化。微观优化就像“理发减肥”。
答案 15 :(得分:5)
我无法想象一个有价值的编译器会生成任何不同的代码。即使它确实如此,如果没有测试更有效的特定编译器,也无法确定。
但我建议您更喜欢for(;;)
,原因如下:
我使用过的许多编译器都会为while(true)生成一个常量表达式警告,并带有适当的警告级别设置。
在您的示例中,宏TRUE可能未按预期定义
无限while循环有许多可能的变体,例如while(1)
,while(true)
,while(1==1)
等;所以for(;;)
可能会带来更大的一致性。
答案 16 :(得分:5)
for(;;Sleep(50))
{
// Lots of code
}
比以下更清楚:
while(true)
{
// Lots of code
Sleep(50);
}
如果您不使用Sleep()
,则不适用。
答案 17 :(得分:4)
“永远”循环在嵌入式系统中作为后台循环很流行。有些人将其实现为:
for (; ;)
{
// Stuff done in background loop
}
有时它实现为:
while (TRUE /* or use 1 */)
{
// Stuff done in background loop
}
另一个实现是:
do
{
// Stuff done in background loop
} while (1 /* or TRUE */);
优化编译器应为这些片段生成相同或类似的汇编代码。一个重要的注意事项:循环的执行时间并不是一个大问题,因为这些循环会永远持续下去,并且处理部分会花费更多时间。
答案 18 :(得分:2)
我认为while(true)比(;;)更可读 - 它看起来像程序员错过for循环中的东西:)
谁在乎哪一个更快
答案 19 :(得分:2)
使用“for(;;)”的最重要原因是在进行探索性编程时担心使用“while(TRUE)”。使用“for”控制重复次数更容易,并且更容易将“for”循环转换为无限循环。
例如,如果要构造递归函数,则可以在转换为无限循环之前限制对函数的调用量。
for(int i=0;i<1000;i++) recursiveFunction(oneParam);
当我确定我的功能时,我将其转换为无限循环:
for(;;) recursiveFunction(oneParam);
答案 20 :(得分:0)
正如其他人所指出的,从技术角度来看,这根本无关紧要。有些人认为一种比另一种更具可读性,他们对此有不同的看法。
对我来说,这基本上只是吹毛求疵,因为任何 C 程序员都应该能够立即将 while(1)
和 for(;;)
识别为无限循环。
您的定义不起作用。但是,您可以(但不应该)这样做:
#define repeat for(;;)
int main(void)
{
repeat {
puts("Hello, World");
}
}
但是真的,不要做那样的事情......