简体   繁体   中英

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?

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)?

  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.

One is that some compilers produce warnings on while(true) (something like "loop condition is constant"). Avoiding warnings is always a good thing to do.

Another is that I think for(;;) is clearer and more telling. 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? I'm not interested in looping until true becomes false, which is what this form literally says (loop while true is 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. I prefer it to while (true) , while (1) , while (42) , while (!0) etc etc.

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.

  • This is idiomatic 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.

  • Your #define won't work, since the thing being #define'd has to look like a C identifier.

  • 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.

If you're curious, here is what gcc 4.4.1 gives me for x86. Both use the x86 JMP instruction.

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.

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. 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) . In PHP, keywords are case-insensitive but the language prefers the capitalization TRUE .

However, for (;;) is always completely correct in all of those languages.

I personally prefer the for (;;) idiom (which will compile to the same code as while (TRUE) .

Using while (TRUE) may be more readable in one sense, I've decided to use the for (;;) idiom because it stands out .

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) .

Also, I recall that some compilers issue warnings when the controlling expression of a while loop is a constant. 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 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).

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:

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. There is extra instructions for the true condition inside 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)  

However, if you build your code in Release mode (with default Maximize Speed (/O2) ) you get same output for both. 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). 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.

I find if faster to type "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.

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)

(My TypingTest.com benchmark = 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.

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() .

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:

  • a number of compilers I have used will generate a constant expression warning for while(true) with appropriate warning level settings.

  • in your example the macro TRUE may not be defined as you expect

  • there are many possible variants of the infinite while loop such as while(1) , while(true) , while(1==1) etc.; so for(;;) is likely to result in greater consistency.

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. It's easier to control the amount of repetitions with "for", and also, easier to convert the "for" loop into an infinite.

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.

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...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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