Chr*_*per 160 c c++ optimization readability infinite-loop
for (;;) {
//Something to be done repeatedly
}
Run Code Online (Sandbox Code Playgroud)
我已经看到这种东西使用了很多,但我觉得它很奇怪......说再说清楚while(true),还是沿着这些方向做些什么?
我猜这(因为许多程序员采用神秘的代码的原因)这是一个微小的利润更快?
为什么,它真的值得吗?如果是这样,为什么不这样定义它:
#define while(true) for(;;)
Run Code Online (Sandbox Code Playgroud)
Ben*_*tto 259
jal*_*alf 172
我更喜欢for(;;)两个原因.
一个是一些编译器产生警告while(true)(类似"循环条件不变").避免警告总是一件好事.
另一个是我认为for(;;)更清晰,更有说服力.我想要一个无限循环.它的字面有没有条件,这取决于什么.我只是想让它永远持续下去,直到我做一些事情来突破它.
然而while(true),嗯,什么是真的与任何事情有关?我对循环不感兴趣,直到true变为false,这就是这个形式的字面意思(循环,而true为真).我只是想循环.
不,绝对没有性能差异.
ta.*_*.is 56
我个人使用,for (;;)因为它没有任何数字,它只是一个关键字.我喜欢它while (true),while (1),while (42),while (!0)等等等等.
Mar*_*son 49
因为丹尼斯里奇
我开始使用,for (;;)因为这就是Dennis Ritchie在K&R中所做的事情,当我学习一门新语言时,我总是试图模仿聪明人.
这是惯用的C/C++.如果您计划在C/C++空间做很多事情,那么从长远来看,它可能会更好地适应它.
你#define将无法工作,因为#define'd必须看起来像一个C标识符.
所有现代编译器都将为这两个构造生成相同的代码.
Mat*_*hen 46
在任何理智的编译器中它肯定不会更快.它们都将编译成无条件跳转.for版本更容易输入(如Neil所说),如果您了解循环语法,那么将会很清楚.
如果你很好奇,这就是gcc 4.4.1给我的x86.两者都使用x86 JMP指令.
void while_infinite()
{
while(1)
{
puts("while");
}
}
void for_infinite()
{
for(;;)
{
puts("for");
}
}
Run Code Online (Sandbox Code Playgroud)
汇编到(部分):
.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
Run Code Online (Sandbox Code Playgroud)
Boa*_*ann 42
我更喜欢,for (;;)因为它在不同的C语言中是最一致的.
在C++ while (true)中很好,但在C中你依赖于一个头来定义true,但它TRUE也是一个常用的宏.如果你while (1)在C和C++和JavaScript中使用它是正确的,而不是Java或C#,它要求循环条件是布尔值,例如while (true)或while (1 == 1).在PHP中,关键字不区分大小写,但语言更喜欢大写TRUE.
但是,for (;;)在所有这些语言中总是完全正确的.
Mic*_*urr 21
我个人更喜欢这个for (;;)成语(它将编译为相同的代码while (TRUE).
while (TRUE)在某种意义上,使用可能更具可读性,我决定使用这个for (;;)成语,因为它很突出.
一个无限循环结构应该很容易被注意到或在代码中调用,我个人认为这种for (;;)风格比while (TRUE)或者好一点while (1).
另外,我记得当while循环的控制表达式是常量时,一些编译器会发出警告.我认为这不会发生太多,但只是虚假警告的可能性足以让我想要避免它.
rme*_*dor 17
我见过有些人喜欢它,因为他们有一个像这样的#define:
#define EVER ;;
Run Code Online (Sandbox Code Playgroud)
这允许他们写这个:
for (EVER)
{
/* blah */
}
Run Code Online (Sandbox Code Playgroud)
小智 16
那么(如果你的语言支持它):
start:
/* BLAH */
goto start;
Run Code Online (Sandbox Code Playgroud)
Jas*_*ams 12
生成的机器代码没有区别.
然而,为了逆转这种趋势,我认为while(TRUE)形式比(;;)更具可读性和直观性,而且可读性和清晰度是编码指南的重要原因,而不是任何原因.听说for((;)方法(我更喜欢将我的编码指南建立在坚实的推理和/或自己的有效性证明上).
Mic*_*ael 11
while(true)
Run Code Online (Sandbox Code Playgroud)
使用Visual Studio生成警告(条件是常量).我工作过的大多数地方编译生产版本都会将警告视为错误.所以
for(;;)
Run Code Online (Sandbox Code Playgroud)
是优选的.
小智 11
如果您的代码由编译器优化,则两者应该相同.为了解释我的优化意义,这里是一个用MSVC 10编写的示例代码:
int x = 0;
while(true) // for(;;)
{
x +=1;
printf("%d", x);
}
Run Code Online (Sandbox Code Playgroud)
如果您在调试模式下构建它(没有任何优化(/ 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)
Run Code Online (Sandbox Code Playgroud)
但是,如果在Release模式下构建代码(默认最大化速度(/ 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)
Run Code Online (Sandbox Code Playgroud)
无论你使用哪个,对于具有速度优化的合适编译器都无关紧要.
这是个人偏好的问题,哪种方式更快.就个人而言,我是一个触摸键盘,在编程期间从不看我的键盘 - 我可以触摸键盘上的所有104键.
我发现如果更快输入"while(TRUE)".
我精神上添加了一些手指运动测量并将它们总计."for(;;)"有大约12个键宽度的后退和第四个(在主键和键之间,以及主键和SHIFT键之间)"while(TRUE)"有大约14个键宽度的后退和第四.
但是,在输入后者时,我很容易出错.我一次用心语思考,所以我发现输入像"nIndex"这样的东西比"nIdx"这样的首字母缩略词更快,因为我必须精神上拼出字母,而不是在脑海里说出来让我的手指自动 - 这个词(喜欢骑自行车)
(我的TypingTest.com基准= 136 WPM)
所有好的答案 - 行为应该完全相同.
但是 - 只是假设DID有所作为.假设其中一个每次迭代需要3个指令.
你应该关心吗?
只有你在循环中做的事几乎没有,这几乎不是这样的.
我的观点是,存在微优化和宏优化.微观优化就像"理发减肥".
我无法想象一个有价值的编译器会生成任何不同的代码.即使它确实如此,如果没有测试更有效的特定编译器,也无法确定.
不过我建议你更喜欢for(;;)以下原因:
我使用过的一些编译器会为while(true)生成一个常量表达式警告,并带有适当的警告级别设置.
在您的示例中,宏TRUE可能未按预期定义
有无限的while循环如许多可能的变型while(1),while(true),while(1==1)等; 因此for(;;)可能会带来更大的一致性.
for(;;Sleep(50))
{
// Lots of code
}
Run Code Online (Sandbox Code Playgroud)
比以下更清楚:
while(true)
{
// Lots of code
Sleep(50);
}
Run Code Online (Sandbox Code Playgroud)
如果你不使用,这并不适用Sleep().