代码之家  ›  专栏  ›  技术社区  ›  Chris Cooper

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

  •  156
  • Chris Cooper  · 技术社区  · 15 年前
    for (;;) {
        //Something to be done repeatedly
    }
    

    不是说得更清楚了吗 while(true) 或者类似的东西?

    为什么,是吗 值得的?如果是,为什么不这样定义:

    #define while(true) for(;;)
    

    另请参见: Which is faster: while(1) or while(2)?

    20 回复  |  直到 8 年前
        1
  •  272
  •   Ben Zotto sberry    15 年前
    1. 不是更快。
    2. 如果你真的关心,用汇编输出编译你的平台,看看。
        2
  •  183
  •   Stack Overflow is garbage    15 年前

    我更喜欢 for(;;) 有两个原因。

    一是一些编译器在 while(true)

    另一个是我认为 对于(;;) 我想要一个无限循环。真的吗 没有条件,这不取决于什么。我只想让它永远延续下去,直到我做点什么来打破它。

    while(真)

        3
  •  57
  •   ta.speot.is    15 年前

    就我个人而言 for (;;) 因为里面没有数字,只是个关键词。我更喜欢它 while (true) , while (1) , while (42) , while (!0) 等等等等。

        4
  •  51
  •   Mark Harrison    15 年前

    • 我开始使用 for (;;) 因为丹尼斯·里奇在K&中就是这么做的;R、 当我学习一门新语言时,我总是努力模仿聪明人。

    • 你的 #define 不起作用,因为被定义的东西必须看起来像C标识符。

    • 所有现代编译器都将为这两种结构生成相同的代码。

        5
  •  46
  •   Matthew Flaschen    15 年前

    在任何一个健全的编译器中,它肯定不会更快。它们都将被编译成无条件跳转。for版本更容易输入(正如Neil所说),如果您理解for循环语法,它将变得更清晰。

    如果您好奇,下面是GCC4.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
    
        6
  •  44
  •   Boann    10 年前

    我更喜欢 for (;;) 因为它在不同的C语言中是最一致的。

    while (true) 很好,但在C中,您依赖于头来定义 true TRUE 也是常用的宏。如果你使用 while (1) 在C和C++中,JavaScript是正确的,但是java或C语言都是正确的,这要求循环条件是一个布尔值,例如 while(真) while (1 == 1) . 在PHP中,关键字不区分大小写,但该语言更喜欢大写 真的 .

    然而, 对于(;;)

        7
  •  21
  •   Michael Burr    15 年前

    我个人更喜欢 for (;;) 习惯用法(编译成与 while (TRUE) .

    while(真) 从某种意义上说,可能更具可读性,我决定使用 对于(;;) 它脱颖而出

    无限循环构造应该很容易在代码中被注意或调用,我个人认为 对于(;;) while(真) while (1) .

    另外,我记得当while循环的控制表达式是常量时,有些编译器会发出警告。我不认为这种情况发生得太多,但仅仅是潜在的虚假警告就足以让我想避免它。

        8
  •  19
  •   rmeador    15 年前

    我见过一些人喜欢它,因为他们有这样的定义:

    #define EVER ;;
    

    这样他们就可以写下:

    for (EVER)
    {
        /* blah */
    }
    
        9
  •  16
  •   bungle    15 年前

    start:
    /* BLAH */
    goto start;
    
        10
  •  13
  •   Jason Williams    15 年前

    在生成的机器代码方面没有区别。

        11
  •  11
  •   James McLeod    15 年前

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

        12
  •  11
  •   Michael    15 年前
    while(true)
    

    for(;;)
    

    首选。

        13
  •  11
  •   SylvanBlack    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)  
    

    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)  
    

    不管你用哪一个都不重要,因为一个有速度优化功能的好编译器是开着的。

        14
  •  10
  •   Mark Rejhon    15 年前

    这是个人喜好的问题,哪条路更快。就我个人而言,我是一个触摸打字员,在编程过程中从不看键盘——我可以触摸键盘上的所有104个键。

    我在心里加了一些手指运动的测量值,然后把它们加起来。 “对于(;)”有大约12个键宽的来回和第四次移动(在home键和键之间,以及home键和SHIFT键之间)

    但是,我在输入后者时不太容易出错。我在心里一次用词思考,所以我发现像“nIndex”这样的单词比像“nIdx”这样的缩写词打字要快,因为我必须在心里把字母拼出来,而不是在心里说出来,让我的手指自动打字(比如骑自行车)

        15
  •  6
  •   Mike Dunlavey    15 年前

    所有好的答案-行为应该完全相同。

    不过,假设它确实起了作用。假设其中一个在每次迭代中多执行3条指令。

    只有当你在循环中做的是 几乎什么都没有 几乎从来没有 这个案子。

    我的观点是,有微观优化和宏观优化。微优化就像“理发减肥”。

        16
  •  5
  •   Clifford    15 年前

    我无法想象一个有价值的编译器会产生任何不同的代码。即使它这样做了,也没有办法在不测试特定编译器的情况下确定哪个编译器更有效。

    不过我建议你还是 for(;;)

    • 我使用的许多编译器都会生成一个常量表达式警告while(true),并带有适当的警告级别设置。

    • 在您的示例中,宏TRUE可能没有如您所期望的那样定义

    • while(1) while(true) , while(1==1) 对于(;;)

        17
  •  5
  •   Anatoliy Nikolaev    11 年前
    for(;;Sleep(50))
    {
        // Lots of code
    }
    

    是比以下更清楚的:

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

    Sleep() .

        18
  •  4
  •   Thomas Matthews    15 年前

    “forever”循环作为后台循环在嵌入式系统中很流行。有些人将其作为:

    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 */);
    

        19
  •  3
  •   nik    5 年前

    看起来程序员在for循环中遗漏了一些东西 :)

        20
  •  2
  •   Ignacio Cortorreal    9 年前

    使用“for(;;)”最重要的原因是在进行探索性编程时害怕使用“while(TRUE)”。用“for”更容易控制重复的次数,也更容易将“for”循环转换为无限循环。

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

    当我确定了我的函数,然后我把它转换成一个无限循环:

        for(;;) recursiveFunction(oneParam);
    
        21
  •  0
  •   klutt    4 年前

    正如其他人所指出的,从技术角度看,这一点都不重要。有些人认为其中一个比另一个更易读,他们对哪一个有不同的看法。

    对我来说,这基本上只是吹毛求疵,因为任何C程序员都应该能够做到 立即 认识两者 while(1) for(;;) 无限循环。

    你的定义行不通。但是,您可以(但不应该)这样做:

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

    但真的,不要这样做。。。