1 2 3
| for (;;) {
//Something to be done repeatedly
} |
我见过这种东西用得很多,但我觉得很奇怪…难道说while(true)或是其他类似的话就更清楚了吗?
我猜(许多程序员使用密码的原因也是如此),这是一个小范围的更快吗?
为什么,它真的值得吗?如果是这样,为什么不直接用这种方式来定义它呢?
1
| #define while(true) for(;;) |
另请参见:哪个更快:while(1)或while(2)?
- 什么是TRUE????
- true是1,true是win32 afaik的定义
- @斯梅林:可能。但在一个没有提到Win32的问题上,它在做什么呢?
- 如果这是C++,那么使用EDCOX1×0。对于c,使用TRUE。这就是全部。
- 我假设true被定义为1,用作伪布尔值。
- @史蒂文·苏迪特:TRUE与C有什么关系?c99中真正布尔值结果的标准宏仍然是TRUE。TRUE是从哪里来的?
- 我个人认为for(;;)是更清晰的结构。while (true)意味着您正在测试TRUE的每个循环;显然,我知道这是经过优化的,但这是不必要的代码。
- 这个宏不起作用,但在ioccc中使用了#define EVER ;;。:)
- 我只是在想"无限循环"这个词有点误导人,因为实际上我们不是指无限的,因为仍然存在循环中断的条件。相反,我们的意思是它是一个"循环,其复杂条件超出了语言内置构造支持循环的能力"。只是条件不一定是一个表达式,但可能是一个事件或类似的事情。
- 包含的某些头为windows bool类型定义了true。这可能就是它的来源。这在Win32编程中很常见。
- 只是不要为(;;)写信;否则你可能会遇到麻烦。
- 不是#define while(TRUE)的宏声明了一个宏,它采用了一个从未使用过的参数TRUE,因此将程序中的每个while循环都转换为无限循环吗?
- @安德烈:在vs 6.0中,标准宏是TRUE。
- @史蒂文·苏迪特:没有。没有"标准宏在vs 6.0中"。宏TRUE来自与Windows API关联的头文件。这与6.0相比没有任何关系。正如我之前说过的,它与C或C++无关。在C++中,"真"字面只是TRUE(也在VS 6中),在C89/90中根本没有这样的东西,而在C99中,它是宏EDCOX1〔0〕。这适用于所有C/C++编译器。
- @安德烈:我觉得你是在挑肥拣瘦,而不是很有用。Vs6.0附带了windows sdk头文件,在默认项目中stdafx.h中包含这些头文件。这个头文件有一个TRUE定义。这个定义在C Windows SDK中已经有一段时间了,比EDOCX1对0语言的添加还要早,这就是为什么我把它称为C++而不是C。现在我已经解释了我自己,我真的对过去这一点的争论不感兴趣。
- 重点是:它不可移植…
- @史蒂文:没有这样简单的事实。
- @另外,我相信你不是天生的老鹰。
- 我看到有些人用"goto"来表示无限循环。"转到"最快吗?
- @格曼尼克:你不能处理好事实。也就是说,所有非Windows用户。
- 所以事实上有人问过for (;;)是否更快(???)比while (1)还要多。对程序员社区的信心再次丧失。
- 没有人指出:for(;;)只有7个字符,其中while(true)为11,甚至while(1)为8。因此,从一个狂热的应用程序开发的角度来看,我们都应该清楚地使用for。尤其是当;;利用通常被QWERTY浪费的有价值的家庭房地产时。
- 实际上,#define EVER ;;从未在ioccc中使用过,至少没有在一个获胜的条目中使用过。当我第一次学习C时,我确实使用了#define EVER ;;,或者可能是#define EVER (;;)。当时,我觉得它很聪明。我仍然认为这很聪明;我不再认为这是好事。
速度不快。
如果您真的很在意,可以使用平台的汇编程序输出进行编译并查看。
没关系。这无关紧要。写出你喜欢的无限循环。
- 直观地说,优化无限循环提供了无限加速的潜力。好的是,我们不根据直觉编程。-)
- 我想你是对的。我想我正卷入关于小事情的"宗教"辩论中。感谢你让我的良心得到解脱。D
- @史蒂文·洛尔,这很有趣,但是考虑到你真正达到无限加速潜力的唯一情况是循环永远不会中断并且真正无限地运行,这很可能是一个bug,或者如果是有意的话,在它达到这个潜力之前是一个无限的等待。
- 我觉得他在开玩笑。P
- @克里斯。在编程和生活中,宗教辩论只值得你花时间去做真正重要的事情。这不是其中之一。正如你所看到的,每个人都有一个可爱的方式来写一个永无止境的循环。为你自己挑选那些能让你最开心的事情,然后在重要的代码上运行分析器。:)
- @史蒂文·苏迪特:许多amiga软件都是通过直觉编程开发出来的。:)
- @BK1E:不同种类。
- @啊,但是它是一个基数更高的无穷大!(证明我是白白上大学的。)
- 它确实很重要,因为一些平台上的早期编译器确实加载了一个常量并对其进行了条件跳转。在那些日子里,硬件确实很重要。
- 我用goto写不定式循环
- 它对人类很重要。为什么你不该写(2)
- 我使用for(;;)作为while(true)将生成有关常量条件表达式的警告。
我喜欢for(;;)有两个原因。
一种是有些编译器在while(true)上产生警告(类似于"循环条件是常量")。避免警告总是一件好事。
另一个原因是我认为for(;;)更清晰,更有说服力。我想要一个无限循环。它实际上没有条件,它什么也不依赖。我只希望它永远持续下去,直到我做了一些事情来摆脱它。
而对于while(true),那么,什么是真的呢?我对循环不感兴趣,直到"真"变为"假",这就是这个形式的字面意思(循环而"真"是真)。我只想循环。
不,绝对没有性能差异。
- +1避免警告。但就清晰度而言,我发现在这方面比在这方面更清晰。我想这是个人喜好造成的。
- 是的,偏好和习惯。如果你不习惯看for(;;)的话,这看起来很奇怪。但是我建议你试着习惯它,因为它是一个常见的习语,你会再次碰到它。;)
- 我相信我会再次遇到,但这并不意味着这是一个很好的实践=P。我同意蒂姆的观点,"while"更能说明问题,因为"for"通常在你想做一些特定次数的事情时使用。正如jalf所说,"for(;)"没有条件。为什么没有条件与新条件相同?如果我说"不要在任何情况下做这件事",那意味着永远不要做这件事。不管怎样,那只是我的拿手好戏。=)
- 它没有条件:它是一个无条件循环。我确实想做一些"指定次数"的事情。这个数字就是无穷大。while如何更好?你通常在条件改变之前使用它。这永远不会发生。我不关心1==1,或42>0或true的计算结果是真的。所有这些都只是迂回地说"继续这样做"。所有这些都可以放在一个while循环中,以实现相同的目标。但是当我们已经有了一个特定的循环形式时,为什么要跳过所有这些循环呢?
- @如果for(;condition;)做了同样的事情,在什么情况下你会使用while(condition)循环吗?在对while(true)的辩护中,它明确地指出"延续条件总是成立的",即"永远延续"。for(;;)含蓄地说了同样的话,因为一个特殊的语言规则,省略条件意味着总是继续。从逻辑上讲,它可以很容易地意味着总是中断,但当然,循环零次远不如循环永远有用。或者根本不被允许。所以不管你用什么,它都是一个"特殊的成语"。
- 为了表达我的兴趣,我通常会写while(true),但我认为两者都是非常清楚的,既不清晰,也不可读,也不简单。我想写的是loop { ... },或者{ ... ; continue; },但没关系。我倾向于避免任何导致"我做这个的次数等于无穷大"的陈述,因为我有数学学位,这很痛苦;-)
- JALF对它惯用的评论就是这里的答案。它通常用于"无限循环",因为它是用C语言编写"无限循环"的常用方法。不必有很好的理由来使用一个习语——它只是一个自我强化的约定。
- @卡夫:说得对。代码猴子看,代码猴子做。不过,让人放心的是,JALF也看到了除了熟悉以外的优势:—)
- 不过,文化习俗很重要——它们使我们能够更有效地交流。
- @史提夫:我不明白为什么我会用for(;condition;)。这就是while循环的目的。但正如我所说,对于无限循环,我不希望编译器比较任何条件。天真的是,使用一个while循环,它必须在每次迭代中测试true(显然,即使是最笨的编译器也不会这样做,但这是困扰我的原则。这让我觉得你的代码太过指定了),而使用for(;;),你的字面意思是"没有测试的条件"。只需循环"。我发现它最接近你想象中的loop {...}。
- 但是,我们很清楚,这不是我强烈感觉到的。我完全没有问题看到我必须使用的代码中的while(true),我认为两者都是完全可读的。我只是在解释为什么我认为for(;;)更好。
- 够公平的。我只是问,因为你说"我们已经有了一个具体的循环表",所以我想知道你是否和Go持相同的观点,我们只需要"for"。显然不是:—)
- 他们实际上除了做什么都没有移除……而只是把它混为一谈。for的所有"参数"都是可选的,因此在go中无限循环是for { ... }。for { ... }相当于while循环,循环有一个普通的三个子句,最后for i := range { ... }是foreach循环。有道理,虽然我只使用了go一点,但它仍然在我的头脑中,同样的关键字用于所有的事情;-)
- 如果while(true)发出警告,编译器会很糟糕。
- 艾伯特:微软Visual C++开发者似乎并不认同你的观点。
- 我不太清楚为什么,但是对我来说,EDCOX1(3)简洁地代表了C(和C++,继承的)典型的缺点。比起对数组的可怕处理来说,要比对数字编程的重视程度要低得多,甚至比C标准中的14页概括的未定义行为还要严重,更糟糕的是,"C++中存在的大量UB使我们感到尴尬,甚至在附录中也不把它概括在附录中"。
- 我的经验是,包含for(;;)的答案在堆栈溢出时会被否决,如果与while(true)相同的答案会获得上票。
我个人使用for (;;),因为里面没有数字,只是一个关键字。我比较喜欢while (true)、while (1)、while (42)、while (!0)等。
- +1.指出它不依赖于幻数。
- 0、1和无穷大是可以接受的幻数,将0和1扩展为"假"和"真"并不是一种损失。true不比for是一个魔术关键字或for(;;)使用隐含的魔术无穷大更是一个魔术数字。(以东十一〔七〕的确令人憎恶。)
- Tangent:我的一位CS教授说:"编程中只有三个数字:0、1和N。其他的都叫做幻数。"
- 同意0和1是可接受的幻数。
- @吉诃多:这是一个很好的引语。
- 除了在vb中,其中真正的整数强制转换为-1。
- while (0x1001)—只有0和1,这里没有幻数
- 虽然(42)是最酷的,但在while(1)或while(true)或while(while)方面不会产生不同的结果!0),具有哲学意义。我想for(;;)的解析速度比其他的更快。
- @新竹邹对江户十一〔12〕江户十一〔13〕好得多。
- 那么,while(true)也不包含任何数字。for(;;)不是关键字
- @RIAD只将短语作为一个关键字进行解析。
- 那么for(0xEFAAAAAA)呢?
因为丹尼斯·里奇
我开始使用for (;;),因为丹尼斯·里奇在K&R中就是这样做的,当我学习一门新语言时,我总是试图模仿聪明人。
这是惯用的C/C++。如果你计划在C/C++空间中做很多事情,从长远来看,习惯它可能更好。
你的#define不起作用,因为被定义的东西必须看起来像C标识符。
所有现代编译器都将为这两个构造生成相同的代码。
- 是的,这就是你知道有人从K&R学习C的方式,也就是应该学习C的方式。每当我看到while(TRUE)时,我都怀疑程序员是C新手,或者从A学习C,以获得仿制品。
- 我听说那些新手也使用新的函数定义样式。
在任何正常的编译器中都不会更快。它们都将被编译成无条件跳转。for版本更容易输入(如Neil所说),如果您理解for循环语法,它将是清晰的。
如果你好奇的话,这里是GCC4.4.1给我的x86版本。两者都使用x86 JMP指令。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| void while_infinite()
{
while(1)
{
puts("while");
}
}
void for_infinite()
{
for(;;)
{
puts("for");
}
} |
编译为(部分):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| .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 |
- 我怀疑它甚至在调试模式下也更快。
- for_infinite更快;puts的字符更少。
我更喜欢for (;;),因为它在不同的类C语言中是最一致的。
在C++ EDCOX1中,5是很好的,但是在C中,你依赖于一个头来定义EDCOX1×15,而EDCOX1×15是一个常用的宏。如果你使用EDCOX1,10,它在C和C++中是正确的,而JavaScript,而不是Java或C语言,它要求循环条件是布尔的,比如EDCX1,5,EDCX1,19。在PHP中,关键字不区分大小写,但语言更喜欢大写的true。
然而,for (;;)在所有这些语言中总是完全正确的。
- 谢谢你的回答!我认为这实际上是第一个客观的答案,显示了for (;;)更好。
- 我认为我不需要在C、C++、JavaScript、Java和C语言中编写正确的代码。它们是不同的语言。
- @KeithThompson这不是关于在许多语言中编写正确的代码;我认为这是为了避免不同背景的开发人员之间的误解。
- @山姆:while (1)和for (;;)都是C语言中无限循环的常用习语。任何一个读C程序的人如果不理解这两个程序,可能会对其余的代码产生问题。写一些不懂C语言的人很容易就能读到的C语言代码是不值得的。
- @KeithThompson虽然是一个精通C语言的读者,但绝对应该熟悉这两个习语,如果作者是一个多语言程序员,这也会很有用。在我上一份工作中,我每天都在JS、ActionScript和PHP中工作,并且统一编写代码的方式(这样做很有意义)可以使编程更快,维护更容易。
- 这是切换到for的一个很好的理由,因为我已经被这篇文章中的内容烧掉了。
我个人更喜欢for (;;)习惯用法(它将编译成与while (TRUE)相同的代码)。
从某种意义上讲,使用while (TRUE)可能更易读,我决定使用for (;;)成语,因为它很突出。
无限循环结构应该很容易在代码中被注意到或调用,我个人认为for (;;)样式比while (TRUE)或while (1)样式做得更好。
此外,我还记得当while循环的控制表达式是常量时,一些编译器会发出警告。我不认为这种情况发生的太多,但仅仅是虚假警告的可能性就足以让我想避免它。
我看到有些人喜欢它,因为他们有一个这样的定义:
允许他们写下:
1 2 3 4
| for (EVER)
{
/* blah */
} |
- 我也看到过,但这不是一个很好的理由。作为一名维护人员,您仍然需要检查宏定义,以确保它按照预期的方式执行,而原始代码已经足够清晰了。RTOS VXWorks有一个宏FOREVER定义的for(;;),但没有更好的定义。IMO宏不应用于"发明"新语言。
- 实际上,在某些语言中宏的目的是发明新的语法。但无论在C/C++中,"永远"都是令人发指的。
- 有些人会做一些有趣的事情,比如说如果他们喜欢帕斯卡,他们会说埃多克斯(2)和埃多克斯(3)。我甚至见过#define DONKEYS_FLY (0),所以他们可以说if DONKEYS_FLY ...。谁说软件很枯燥?
- 从我对这个问题的评论中抄袭而来,我指出它只用于幽默/模糊的目的。不要在真正的代码中这样做。
- 在加利福尼亚,我相信你必须永远为……定义。
- 我无法抗拒:#define never while(0)和#define always。
那(如果你的语言支持它的话)呢?
1 2 3
| start:
/* BLAH */
goto start; |
- …应该在任何合理的编译器手中生成相同的输出。
- + 1!它并没有改善goto的许多缺点,但是,如果您试图实现的算法来自流程图,那么这是最直接的转换。
- 当心猛禽…
- 我个人对Goto持功利主义的观点。没有猛禽。猛禽是人类。正是这些人开始使用Goto制作意大利面代码。另外,一个循环的组装输出看起来非常像这样。计算机指令集没有"for"或"while"的概念,只是"跳转"。
- 从未使用过EDOCX1[0]
- 关于goto,真正的好处是你不必担心有人添加break来减少循环的无限性。(除非你已经在另一个while或for循环中……)
在生成的机器代码方面没有区别。
然而,为了顺应这一趋势,我认为while(true)形式比(;;)形式更易于阅读和直观,可读性和清晰性是编码指南的重要原因,而不是我听说的for(;)方法的任何原因(我更喜欢将我的编码指南建立在可靠的推理和/或有效性证明的基础上自我)。
- 这取决于你的语言。EDCOX1 6是C和C++中的传统方法。EDCOX1〔14〕似乎是C语言、Java语言和其他语言的约定。您的里程可能会有所不同。
- 但是对C或C++不太熟悉的人会更容易读(真),熟悉的人也会理解,因此更可读。
- 是的,那些对C或C++不太熟悉的人可能会发现StangySCAN格式比SCANF更可读,但是你没有看到任何人在他们的代码顶端放置了SrangyScript格式的SCASNF。
- 我想说,惯用的方法最好对您的开发人员来说是最易读的。否则你真的需要更好的开发人员。
- @ DeStase:如果有人不太熟悉C++来识别那个习语是什么,那么他们需要远离我的代码库。
- 我同意惯用的方法应该是最易读的。这就是为什么随着语言和实践的发展,惯用方法总是需要被挑战和改变的原因。糟糕的K&R"惯用"编码风格用现代、可读性更强的风格取代了它,这花了多年时间,但它仍然存在。
如果您的代码是由编译器优化的,那么两者应该是相同的。为了解释我所说的优化,这里有一个用MSVC 10编写的示例代码:
1 2 3 4 5 6 7 8
| int x = 0;
while(true) // for(;;)
{
x +=1;
printf("%d", x);
} |
如果您在调试模式下构建它(没有任何优化(/od)),反汇编将显示出明显的区别。对于while中的true条件有额外的说明。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 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)),则两种方法的输出相同。两个循环都被简化为一个跳转指令。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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) |
无论您将使用哪一种,对于一个具有速度优化功能的优秀编译器来说都无关紧要。
- 这实际上是一个很好的观点!如果没有优化,即使是现代编译器也会因几个指令而有所不同。
使用Visual Studio生成警告(条件为常量)。我工作过的大多数地方都会编译生产版本,并将警告作为错误。所以
优先考虑。
- 您使用的是什么版本的Visual Studio?在2008年,我没有得到这个警告,即使是在4级警告。
- Visual Studio 2005,SP1版
不仅是众所周知的模式,而且是C(和C++)中的标准成语。
- 是的,我认为有些编译器在while (true)上发出警告的原因与在if (true)上发出警告的原因相同。
这是个人喜好的问题,哪种方式更快。就我个人而言,我是一个触摸式打字员,在编程过程中从不看我的键盘——我可以触摸键盘上的所有104个键。
我发现输入"while(true)"的速度是否更快。
我在心里加了一些手指运动的测量值,然后把它们加起来。"for(;)"有大约12个键宽的向后和第四个移动(在主键和键之间,以及在主键和SHIFT键之间)"while(true)"有大约14个前后移动的关键宽度。
但是,在输入后者时,我很少出错。我每次都会用文字思考,所以我发现打字"nindex"比用缩写词"nidx"更快,因为我必须在心里拼出字母,而不是在心里说出来,让我的手指自动打字(就像骑自行车一样)。
(my typingtest.com基准=136 wpm)
- 洛尔乌特?15焦
- 我认为操作是指运行时速度,而不是输入速度。
- 我知道。也必须覆盖那个基地。
- S/个人偏好/个人习惯/
- @samb:评论投票支持s///。是的,虽然我建议这可能是由于运行时的速度,但我不知道实际的答案。如果是这样,我会很高兴的。
- 运行time head -10 >/dev/null,每键入10次,测量结果。我敢打赌,除非你作弊,否则你在for(;;)的速度会更快。我当时大约14%。
所有好的答案-行为应该完全相同。
但是-假设它确实有影响。假设其中一个在每次迭代中多接受了3条指令。
你应该关心吗?
只有当你在循环中所做的几乎是什么都不是的时候,这几乎是不可能的。
我的观点是,有微观优化和宏观优化。微观优化就像"理发减肥"。
- 你多久会看到人们被告知更喜欢++i而不是i++?
- @Dennis Zickefoose:如果i是类的实例而不是内置的,并且编译器不应用琐碎的优化,那么++i和i++之间的差异可能非常显著。建议是养成一个习惯,这样它在重要的时候就不会把你抓出来。
- 关于++i和i++的问题是,进行"优化"不需要花费任何代价。是的,在大多数情况下,它完全没有区别,但是它们同样容易输入,所以为什么不在默认情况下选择潜在的最有效的呢?我想这里也同样适用。如果其中一个比另一个快一点点,为什么不去找更快的呢?我们这样做会失去什么?两者都相当容易读取和打印。
- @克利福德:@jalf:I am trying to lost weight:-),and I do get hairscuts,but arguments of the form:"You would save a micro cent so why not do it?"不要给我留下太多印象,因为忽略它只需要一个微观的原因,比如"太阳在照耀着,那为什么还要考虑它呢?"
- @丹尼斯:你说得对。我看了很多,克利福德的评论是对的。此外,还有一些事情我看不太清楚,那就是如何进行宏优化,比如43x加速:stackoverflow.com/questions/926266/…。所以我想知道我们的优先事项。
- @克利福德:虽然我完全理解你的观点(作为一名飞行员,这种推理是必要的),但在编程中,我总是要深入到细节。例如,在少数情况下,我看到交换++和i在性能上发生了重大变化,因为i是一个类实例,用整数替换i在性能上发生了更大的变化。"你说,不能总是这样吗?也许吧,但我们在这里得到了真正的假设,在任何情况下,宏优化都可以用来精确定位问题。
- @迈克:是的,但那是苹果和橙子的比较。理发需要实际的时间,甚至可能需要钱。我同意这是一个微观的优化,所以这并不重要。但这也不会让我们付出任何代价。如果我可以选择向左或向右走,而且距离是一样的,地形是一样的,一切都是一样的,除了左边的小路有一些边际的微观效益,为什么不向左走呢?你说得对,这不是一个令人印象深刻的争论。但当成本为零时,我看不出有理由选择不太理想的路线。
- 我不是真的不同意你。我同意你仍然不应该在意使用哪一种,但是风格的一致性很重要。如果两个选项的可读性相同,您也可以选择保存三个时钟周期的样式。如果太阳在照耀,或者你觉得while(1)比for(;;)更具描述性,那么不管丢失的时钟周期如何,都要使用它。即使这段代码被证明是有问题的,也可能不是因为您选择的循环类型。根据类似的逻辑,我总是在自己的代码中使用i++,因为它对我更有意义。
- @迈克·邓拉维:X43加速?尝试CUDA。
- @丹尼斯·齐克福泽:据我所知,我很少自己去写++i,无论如何;-);只是太难看了!如果您调用一个变量i,而它不是一个普通的int,那么可能存在更大的编码风格问题!
- @克利福德:我非常同意。我也很无聊,因为我还没有找到一个幽默的方法来指出,让硬件工程师绞尽脑汁使机器更快、更便宜是多么令人惊讶,而我们编码人员,而不是消除不必要的周期,说"为什么要麻烦?"我脑子里有一个画面,一匹良种的赛马拖着一个400磅重的骑师,或者在跑道上绕了10圈,或者走了很多弯路。
- 在增量前和增量后,您必须注意使用哪一个。差异将改变程序功能,而不仅仅是性能。如果其中一个对你来说"没有意义",那就一定要避免它。在这种情况下,最好切换到foo = foo + 1;并将其保存在单独的语句中。(为了安全起见,不要考虑使用三元运算符?:,当然,这意味着首选的无限循环形式:for(unsigned int i=0; i<0; i = i + 1);。
1 2 3 4
| for(;;Sleep(50))
{
// Lots of code
} |
比以下更清楚:
1 2 3 4 5
| while(true)
{
// Lots of code
Sleep(50);
} |
如果你不使用Sleep(),这并不适用。
- 这是非常糟糕的代码,应该使用计时器而不是睡眠,所以这是个糟糕的例子。
- @是的,你是对的。我的代码很糟糕。下次我做一个无限循环时,我应该更加努力。
- @ST3只是出于兴趣,如何使用计时器对上面的示例进行编码?
- @frammo-取决于你的操作系统,但通常是像timerService.scheduleRepeating (50, [] () { /* lots of code */ });这样的。
- 在这样的for循环中调用类似sleep的函数没有什么好处
- omg,timerservice.schedulerepeating(50,[]())很容易输入和理解,然后睡觉(50)。
我无法想象一个有价值的编译器会生成任何不同的代码。即使是这样,如果不测试更高效的特定编译器,也无法确定。
不过,我建议您选择for(;;),原因如下:
- "真"不能定义为"真1",但任何while(TRUE)评估为while(0)的代码基都不可能从for(;;)中获益。
- 贾斯廷:我同意,这将是真正的反常,它不是三个参数中最强的,但是Bjarne Stoustrup使用类似的论点来避免C++中的NULL宏。在任何情况下,都应优先选择while(TRUE)。在C++ EDCOX1中,12保留是保留的,在C中定义为C StdBoo.h(使它在C中不太安全)。for(;;)消除了所有疑问。
"永远"循环在嵌入式系统中作为一个背景循环很流行。有些人将其实现为:
1 2 3 4
| for (; ;)
{
// Stuff done in background loop
} |
有时它被实现为:
1 2 3 4
| while (TRUE /* or use 1 */)
{
// Stuff done in background loop
} |
另一个实现是:
1 2 3 4
| do
{
// Stuff done in background loop
} while (1 /* or TRUE */); |
优化编译器应该为这些片段生成相同或类似的程序集代码。一个重要的注意事项:循环的执行时间并不是一个大问题,因为这些循环将永远持续下去,而处理部分将花费更多的时间。
- 如果编译器为这些代码生成不同的代码,那么是时候抛弃编译器,从过去20年中获得一个了。
- "循环的执行时间不是一个很大的问题,因为这些循环将永远持续下去"——这对我来说听起来是错误的。
- @盲目——因为它是错误的,所以需要关注的是运行时处理循环逻辑所花费的部分,或者每单位有用工作的循环逻辑的数量,而循环是无限的,这两者都没有帮助。
我假设while(true)比(;;)更可读——它看起来像是程序员遗漏了for循环中的内容:)
谁在乎哪一个更快,如果有的话
使用"for(;;)"最重要的原因是在进行探索性编程时害怕使用"while(true)"。使用"for"可以更容易地控制重复次数,而且更容易将"for"循环转换为无限循环。
例如,如果正在构造递归函数,则可以在转换为无限循环之前限制对该函数的调用量。
1
| for(int i=0;i<1000;i++) recursiveFunction(oneParam); |
当我确定了我的函数后,我把它转换成一个无限循环:
1
| for(;;) recursiveFunction(oneParam); |
- 第一个循环有语法错误(缺少分号)。
- 哈!从而证明for(;);)的缺点