简体   繁体   English

“for(;;)”比“while (TRUE)”快吗? 如果不是,人们为什么要使用它?

[英]Is “for(;;)” faster than “while (TRUE)”? If not, why do people use it?

for (;;) {
    //Something to be done repeatedly
}

I have seen this sort of thing used a lot, but I think it is rather strange... Wouldn't it be much clearer to say while(true) , or something along those lines?我已经看到这种东西经常使用,但我认为它很奇怪......说while(true)或类似的东西不是更清楚吗?

I'm guessing that (as is the reason for many-a-programmer to resort to cryptic code) this is a tiny margin faster?我猜(这也是许多程序员求助于神秘代码的原因)这会快一点吗?

Why, and is it really worth it?为什么,真的值得吗? If so, why not just define it this way:如果是这样,为什么不这样定义它:

#define while(true) for(;;)

See also: Which is faster: while(1) or while(2)?另请参阅: 哪个更快:while(1) 或 while(2)?

  1. It's not faster.它不是更快。
  2. If you really care, compile with assembler output for your platform and look to see.如果您真的很关心,请为您的平台使用汇编器输出进行编译并查看。
  3. It doesn't matter.没关系。 This never matters.这从来都不重要。 Write your infinite loops however you like.随心所欲地编写无限循环。

I prefer for(;;) for two reasons.我更喜欢for(;;)有两个原因。

One is that some compilers produce warnings on while(true) (something like "loop condition is constant").一是一些编译器在while(true)上产生警告(类似于“循环条件是恒定的”)。 Avoiding warnings is always a good thing to do.避免警告总是一件好事。

Another is that I think for(;;) is clearer and more telling.另一个是我认为for(;;)更清晰,更有说服力。 I want an infinite loop.我想要一个无限循环。 It literally has no condition, it depends on nothing.它的字面没有条件,这取决于什么。 I just want it to continue forever, until I do something to break out of it.我只是想让它永远持续下去,直到我做点什么来摆脱它。

Whereas with while(true) , well, what's true got to do with anything?而对于while(true) ,那么 true 与任何事情有什么关系呢? I'm not interested in looping until true becomes false, which is what this form literally says (loop while true is true).我对循环不感兴趣,直到 true 变为 false,这就是这种形式的字面意思(在 true 为 true 时循环)。 I just want to loop.我只想循环。

And no, there is absolutely no performance difference.不,绝对没有性能差异。

Personally I use for (;;) because there aren't any numbers in it, it's just a keyword.我个人使用for (;;)因为里面没有任何数字,它只是一个关键字。 I prefer it to while (true) , while (1) , while (42) , while (!0) etc etc.我更喜欢while (true) , while (1) , while (42) , while (!0)等。

Because of Dennis Ritchie因为丹尼斯·里奇

  • I started using for (;;) because that's the way Dennis Ritchie does it in K&R, and when learning a new language I always try to imitate the smart guys.我开始使用for (;;)是因为 Dennis Ritchie 在 K&R 中就是这样做的,在学习一门新语言时,我总是试图模仿聪明人。

  • This is idiomatic C/C++.这是惯用的 C/C++。 It's probably better in the long run to get used to it if you plan on doing much in the C/C++ space.如果您计划在 C/C++ 领域做很多事情,从长远来看习惯它可能会更好。

  • Your #define won't work, since the thing being #define'd has to look like a C identifier.您的#define将不起作用,因为被 #define'd 的东西必须看起来像一个 C 标识符。

  • All modern compilers will generate the same code for the two constructs.所有现代编译器都会为这两种结构生成相同的代码。

It's certainly not faster in any sane compiler.在任何健全的编译器中它肯定不会更快。 They will both be compiled into unconditional jumps.它们都将被编译成无条件跳转。 The for version is easier to type (as Neil said) and will be clear if you understand for loop syntax. for 版本更容易输入(正如 Neil 所说),如果您了解 for 循环语法,就会很清楚。

If you're curious, here is what gcc 4.4.1 gives me for x86.如果你很好奇,这里是 gcc 4.4.1 为我提供的 x86。 Both use the x86 JMP instruction.两者都使用 x86 JMP指令。

void while_infinite()
{
    while(1)
    {
    puts("while");
    }
}

void for_infinite()
{
    for(;;)
    {
    puts("for");
    }
}

compiles to (in part):编译为(部分):

.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

I prefer for (;;) because it's the most consistent in different C-like languages.我更喜欢for (;;)因为它在不同的类 C 语言中是最一致的。

In C++ while (true) is fine, but in C you depend on a header to define true , yet TRUE is a commonly used macro too.在 C++ 中while (true)很好,但在 C 中你依赖于一个头文件来定义true ,但TRUE也是一个常用的宏。 If you use while (1) it's correct in C and C++, and JavaScript, but not Java or C#, which require the loop condition to be a boolean, such as while (true) or while (1 == 1) .如果您使用while (1)它在 C 和 C++ 以及 JavaScript 中是正确的,但在 Java 或 C# 中是正确的,它们要求循环条件为布尔值,例如while (true)while (1 == 1) In PHP, keywords are case-insensitive but the language prefers the capitalization TRUE .在 PHP 中,关键字不区分大小写,但该语言更喜欢大写TRUE

However, for (;;) is always completely correct in all of those languages.但是, for (;;)在所有这些语言中总是完全正确的。

I personally prefer the for (;;) idiom (which will compile to the same code as while (TRUE) .我个人更喜欢for (;;)习语(它将编译为与while (TRUE)相同的代码。

Using while (TRUE) may be more readable in one sense, I've decided to use the for (;;) idiom because it stands out .使用while (TRUE)在某种意义上可能更具可读性,我决定使用for (;;)习语,因为它很突出

An infinite loop construct should be easily noticed or called out in code, and I personally think the for (;;) style does this a bit better than while (TRUE) or while (1) .一个无限循环结构应该很容易在代码中被注意到或调用,我个人认为for (;;)风格比while (TRUE)while (1)更好。

Also, I recall that some compilers issue warnings when the controlling expression of a while loop is a constant.另外,我记得当 while 循环的控制表达式是一个常量时,一些编译器会发出警告。 I don't think that happens too much, but just the potential for spurious warnings is enough for me to want to avoid it.我不认为这种情况发生得太多,但只是虚假警告的可能性就足以让我想要避免它。

I've seen some people prefer it because they have a #define somewhere like this:我见过有些人喜欢它,因为他们在这样的地方有一个#define:

#define EVER ;;

Which allows them to write this:这允许他们写这个:

for (EVER)
{
    /* blah */
}

What about (if your language supports it):怎么样(如果您的语言支持):

start:
/* BLAH */
goto start;

There's no difference in terms of the machine code that is generated.生成的机器代码没有区别。

However, just to buck the trend, I'd argue that the while(TRUE) form is much more readable and intuitive than for(;;), and that readability and clarity are much more important reasons for coding guidelines than any reasons I've heard for the for(;;) approach (I prefer to base my coding guidelines on solid reasoning and/or proof of effectiveness myself).然而,为了逆势而上,我认为 while(TRUE) 形式比 for(;;) 更具可读性和直观性,并且可读性和清晰度是编码指南的重要原因,而不是我的任何原因我听说过 for(;;) 方法(我更喜欢将我的编码指南建立在可靠的推理和/或有效性证明的基础上)。

Both should be same if your code is optimized by compiler.如果您的代码由编译器优化,两者应该相同。 To explain what I mean by optimization, here is a sample code written in MSVC 10:为了解释我所说的优化是什么意思,这里有一个用 MSVC 10 编写的示例代码:

int x = 0;

while(true) // for(;;)
{
    x +=1;

    printf("%d", x);
}

If you build it in Debug mode ( without any optimization (/Od) ) disassembly shows the clear difference.如果您在 Debug 模式下构建它(没有任何优化 (/Od) ),反汇编显示了明显的区别。 There is extra instructions for the true condition inside while . whiletrue条件有额外的说明。

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)  

However, if you build your code in Release mode (with default Maximize Speed (/O2) ) you get same output for both.但是,如果您在发布模式下构建代码(使用默认的最大化速度 (/O2) ),您将获得相同的输出。 Both loops are reduced to one jump instruction.两个循环都减少为一条跳转指令。

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)  

Whichever you will use does not matter for a decent compiler with speed optimization is on.无论您使用哪种方式,对于速度优化的体面编译器来说都无关紧要。

不仅是一个众所周知的模式,而且是 C(和 C++)中的标准习语

while(true)

generates a warning with Visual Studio (condition is constant).使用 Visual Studio 生成警告(条件不变)。 Most places I've worked compile production builds with warnings as errors.我工作过的大多数地方都编译生产版本,警告为错误。 So所以

for(;;)

is preferred.是首选。

It's a matter of personal preference which way is faster.这是个人喜好的问题,哪种方式更快。 Personally, I am a touchtypist and never look at my keyboard, during programming -- I can touchtype all 104 keys on my keyboard.就我个人而言,我是一名触摸打字员,在编程期间从不看我的键盘——我可以触摸键盘上的所有 104 个键。

I find if faster to type "while (TRUE)".我发现输入“while (TRUE)”是否更快。

I mentally added some finger movement measurements and totalled them up.我在心里添加了一些手指运动测量值并将它们加总。 "for(;;)" has about 12 key-widths of movements back and fourth (between home keys and the keys, and between home keys and SHIFT key) "while (TRUE)" has about 14 key-widths of movements back and fourth. “for(;;)”有大约 12 个键宽的前后移动(在 Home 键和键之间,以及 Home 键和 SHIFT 键之间)“while (TRUE)”有大约 14 个键宽的后退和移动第四。

However, I am vastly less error-prone when typing the latter.但是,我在输入后者时不太容易出错。 I mentally think in words at a time, so I find it faster to type things like "nIndex" than acronyms such as "nIdx" because I have to actually mentally spell out the lettering rather than speak it inside my mind and let my fingers auto-type the word (like riding a bicycle)我在精神上一次用文字思考,所以我发现输入诸如“nIndex”之类的东西比诸如“nIdx”之类的首字母缩写词更快,因为我必须真正在心里拼出字母而不是在我的脑海中说出它并让我的手指自动- 输入单词(如骑自行车)

(My TypingTest.com benchmark = 136 WPM) (我的 TypingTest.com 基准测试 = 136 WPM)

All good answers - behavior should be exactly the same.所有好的答案 - 行为应该完全相同。

HOWEVER - Just suppose it DID make a difference.但是 - 假设它确实有所作为。 Suppose one of them took 3 more instructions per iteration.假设其中一个每次迭代多执行 3 条指令。

Should you care?你应该关心吗?

ONLY if what you do inside the loop is almost nothing , which is almost never the case.仅当您在循环内执行的操作几乎为零时,情况几乎从未如此。

My point is, there is micro-optimization and macro-optimization.我的观点是,有微观优化和宏观优化。 Micro-optimization is like "getting a haircut to lose weight".微优化就像“理发减肥”。

for(;;Sleep(50))
{
    // Lots of code
}

Is a clearer than:比以下更清楚:

while(true)
{
    // Lots of code
    Sleep(50);
}

Not that this applies if you aren't using Sleep() .如果您不使用Sleep() ,这并不适用。

I cannot imagine that a worthwhile compiler would generate any different code.我无法想象一个有价值的编译器会生成任何不同的代码。 Even if it did, there would be no way of determining without testing the particular compiler which was more efficient.即使这样做了,如果不测试更有效的特定编译器,就无法确定。

However I suggest you prefer for(;;) for the following reasons:但是我建议你更喜欢for(;;) ,原因如下:

  • a number of compilers I have used will generate a constant expression warning for while(true) with appropriate warning level settings.我使用过的一些编译器会为 while(true) 生成一个常量表达式警告,并带有适当的警告级别设置。

  • in your example the macro TRUE may not be defined as you expect在您的示例中,宏 TRUE 可能没有按照您的预期定义

  • there are many possible variants of the infinite while loop such as while(1) , while(true) , while(1==1) etc.;无限 while 循环有许多可能的变体,例如while(1)while(true)while(1==1)等; so for(;;) is likely to result in greater consistency.所以for(;;)可能会导致更大的一致性。

The "forever" loop is popular in embedded systems as a background loop. “永远”循环在嵌入式系统中作为后台循环很流行。 Some people implement it as:有些人将其实现为:

for (; ;)
{
 // Stuff done in background loop
}

And sometimes it is implemented as:有时它被实现为:

while (TRUE /* or use 1 */)
{
 // Stuff done in background loop
}

And yet another implementation is:还有一个实现是:

do
{
 // Stuff done in background loop
} while (1 /* or TRUE */);

An optimizing compiler should generate the same or similar assembly code for these fragments.优化编译器应该为这些片段生成相同或相似的汇编代码。 One important note: the execution time for the loops is not a big concern since these loops go on forever, and more time is spent in the processing section.一个重要的注意事项:循环的执行时间不是一个大问题,因为这些循环永远持续下去,而且更多的时间花在处理部分。

我认为 while(true) 比 for(;;) 更具可读性——看起来程序员在 for 循环中遗漏了一些东西:)

The most important reason to use "for(;;)" is the fear of using "while(TRUE)" when you do exploratory programming.使用“for(;;)”的最重要原因是在进行探索性编程时害怕使用“while(TRUE)”。 It's easier to control the amount of repetitions with "for", and also, easier to convert the "for" loop into an infinite.使用“for”更容易控制重复次数,并且更容易将“for”循环转换为无限循环。

For example, if you are constructing a recursive function, you can limit the amount of calls to the function before converting into an infinite loop.例如,如果您正在构建一个递归函数,您可以在转换为无限循环之前限制对该函数的调用量。

    for(int i=0;i<1000;i++) recursiveFunction(oneParam);

When I'm sure of my function, then I convert it to an infinite loop:当我确定我的功能时,我将其转换为无限循环:

    for(;;) recursiveFunction(oneParam);

As others have pointed out, it does not matter at all from a technical view.正如其他人指出的那样,从技术角度来看,这根本无关紧要。 Some people think one is more readable than the other, and they have different opinions about which it is.有些人认为一种比另一种更具可读性,并且他们对此有不同的看法。

To me, that's basically just nitpicking, because any C programmer should be able to instantly recognize both while(1) and for(;;) as infinite loops.对我来说,这基本上只是吹毛求疵,因为任何 C 程序员都应该能够立即while(1)for(;;)识别为无限循环。

Your define will not work.您的定义将不起作用。 However, you CAN (but shouldn't) do this:但是,您可以(但不应该)这样做:

#define repeat for(;;)

int main(void)
{
    repeat {
        puts("Hello, World");
    }
}

But really, DON'T do things like that...但真的,不要做那样的事情......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM