Является ли "for(;;)" быстрее, чем "while (TRUE)"? Если нет, то почему люди используют его?


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

Я видел, что такого рода вещи используются много, но я думаю, что это довольно странно... Не было бы намного яснее сказать while(true), или что-то в этом роде?

Я предполагаю, что (как и причина, по которой многие программисты прибегают к загадочному коду) это крошечный запас быстрее?

почему, и это действительно стоит? Если да, то почему бы просто не определить его следующим образом:

#define while(true) for(;;)

Читайте также: что быстрее: пока(1) или в то время как(2)?

20 149

20 ответов:

  1. Это не быстрее.
  2. Если вы действительно заботитесь, скомпилировать с ассемблером вывода для вашей платформы и посмотреть, чтобы увидеть.
  3. Это не важно. Это не важно. Напишите свои бесконечные циклы, как вам нравится.

предпочитаю for(;;) по двум причинам.

один из них заключается в том, что некоторые компиляторы выдают предупреждения на while(true) (что-то вроде "условие цикла является постоянным"). Избегать предупреждений-это всегда хорошо.

другое что я думаю for(;;) яснее и более красноречиво. Я хочу бесконечный цикл. Это буквально и нет условий, это ни от чего не зависит. Я просто хочу, чтобы это продолжалось вечно, пока я не сделаю что-то, чтобы вырваться из этого.

а с while(true), ну а правда тут при чем? Меня не интересует цикл, пока истина не станет ложной, что буквально говорит эта форма (цикл, когда истина истинна). Я просто хочу сделать петлю.

и нет, нет абсолютно никакой разницы в производительности.

лично я использую for (;;) потому что в нем нет никаких чисел, это просто ключевое слово. Я предпочитаю это while (true),while (1),while (42),while (!0) и т. д. и т. п.

из-за Денниса Ритчи

  • Я начал использовать for (;;) потому что именно так Деннис Ричи делает это в K&R, и при изучении нового языка я всегда стараюсь подражать умным парням.

  • это идиоматический C / C++. Вероятно, в долгосрочной перспективе лучше привыкнуть к нему, если вы планируете много делать в пространстве C/C++.

  • код #define не будет работать, так что #определите, что нужно похож на идентификатор с.

  • все современные компиляторы будут генерировать один и тот же код для двух конструкций.

Это, конечно, не быстрее в любой вменяемый компилятор. Они оба будут скомпилированы в безусловные прыжки. Версия for легче вводить (как сказал Нил) и будет понятна, если вы понимаете синтаксис цикла for.

Если вам интересно, вот что gcc 4.4.1 дает мне для x86. Как использовать х86 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    , %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    , %esp
.L5:
    movl    $.LC1, (%esp)
    call    puts
    jmp .L5
    .size   for_infinite, .-for_infinite

предпочитаю for (;;) потому что это наиболее последовательно в различных C-подобных языках.

В C++ while (true) - это хорошо, но в C вы зависите от заголовка, чтобы определить true, но все же TRUE - это слишком часто используемый макрос. Если вы используете while (1) это правильно в C и C++, и JavaScript, но не Java или C#, которые требуют, чтобы условие цикла было логическим, например while (true) или while (1 == 1). В PHP ключевые слова нечувствительны к регистру, но язык предпочитает капитализацию TRUE.

, for (;;) всегда полностью правильно на всех этих языках.

лично я предпочитаю for (;;) идиома (которая будет компилироваться в тот же код, что и while (TRUE).

используя while (TRUE) может быть более читабельным в одном смысле, я решил использовать for (;;) идиома, потому что он стоит.

бесконечная конструкция цикла должна быть легко замечена или вызвана в коде, и я лично думаю, что for (;;) стиль делает это немного лучше, чем while (TRUE) или while (1).

кроме того, я помню, что некоторые компиляторы выдают предупреждения когда управляющее выражение цикла while является константой. Я не думаю, что это происходит слишком много, но просто потенциал для ложных предупреждений достаточно для меня, чтобы избежать этого.

Я видел, что некоторые люди предпочитают его, потому что у них есть #define где-то так:

#define EVER ;;

что позволяет им писать так:

for (EVER)
{
    /* blah */
}

насчет (если ваш язык поддерживает его):

start:
/* BLAH */
goto start;

нет никакой разницы в терминах машинного кода, который генерируется.

однако, просто чтобы противостоять тенденции, я бы сказал, что форма while(TRUE) гораздо более удобочитаема и интуитивно понятна, чем для (;;), и что читаемость и ясность являются гораздо более важными причинами для руководящих принципов кодирования, чем любые причины, которые я слышал для подхода for (;;) (я предпочитаю основывать свои руководящие принципы кодирования на твердых рассуждениях и/или доказательстве эффективности).

не просто известный шаблон, а стандартная идиома в C (и C++)

while(true)

создает предупреждение с помощью Visual Studio (условие является постоянным). Большинство мест, где я работал, компилируют производственные сборки с предупреждениями как ошибки. Так что

for(;;)

предпочтительнее.

оба должны быть одинаковыми, если ваш код оптимизирован компилятором. Чтобы объяснить, что я имею в виду под оптимизацией, вот пример кода, написанного в 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)  

однако, если вы создаете свой код в режиме выпуска (по умолчанию Максимальная Скорость (/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)  

независимо от того, что вы будете использовать, не имеет значения для приличного компилятора с оптимизацией скорости.

Это вопрос личных предпочтений, какой путь быстрее. Лично я touchtypist и никогда не смотрю на свою клавиатуру, во время программирования-я могу touchtype все 104 клавиши на моей клавиатуре.

Я нахожу, если быстрее ввести " while (TRUE)".

Я мысленно добавил некоторые измерения движения пальцев и суммировал их. "for (;;)" имеет около 12 клавиш-ширины движений назад и четвертого (между клавишами home и клавишами, а также между клавишами home и SHIFT) "пока (правда)" имеет около 14 ключевых Ширин движений назад и в-четвертых.

тем не менее, я значительно менее подвержен ошибкам при вводе последнего. Я мысленно думаю в словах за раз, поэтому я нахожу, что быстрее набирать такие вещи, как" nIndex", чем аббревиатуры, такие как" nIdx", потому что я должен на самом деле мысленно произносить буквы, а не говорить их в своем уме, и пусть мои пальцы автоматически набирают слово (например, езда на велосипеде)

(мой TypingTest.com benchmark = 136 WPM)

все хорошие ответы - поведение должно быть точно так же.

однако-просто предположим, что это действительно имеет значение. Предположим, что один из них взял еще 3 Инструкции за итерацию.

вы должны заботиться?

только если то, что вы делаете внутри цикла почти ничего, которая составляет почти никогда не случае.

моя точка зрения, микро-и макро-оптимизация-оптимизация. Микро-оптимизация похожа на " стрижку, чтобы потерять вес."

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

яснее, чем:

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

не то, что это применимо, если вы не используете Sleep().

Я не могу себе представить, что стоит компилятор будет генерировать другой код. Даже если бы это было так, не было бы никакого способа определить без тестирования конкретного компилятора, который был более эффективным.

однако я предлагаю вам предпочесть for(;;) по следующим причинам:

  • ряд компиляторов, которые я использовал, будут генерировать предупреждение о постоянном выражении для while (true) с соответствующими настройками уровня предупреждения.

  • in ваш пример макрос TRUE может быть определен не так, как вы ожидаете

  • есть много возможных вариантов бесконечного цикла while, такие как while(1),while(true),while(1==1) etc.; так for(;;) вероятно, приведет к большей согласованности.

цикл "навсегда" популярен во встроенных системах в качестве фонового цикла. Некоторые люди реализуют его как:

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

оптимизирующий компилятор должен генерировать тот же или аналогичный ассемблерный код для этих фрагментов. Одно важное замечание: время выполнения для циклов не является большой проблемой, так как эти циклы продолжаются вечно, и больше времени тратится на секция обработки.

Я предполагаю, что while (true) более читаем, чем for (;;)--похоже, программист что-то пропустил в цикле :)

и кого волнует, какой из них быстрее, если таковые имеются

наиболее важной причиной использования "for (;;)" является страх использования "while (TRUE)" при выполнении исследовательского программирования. Легче контролировать количество повторений с помощью "for", а также легче преобразовать цикл" for " в бесконечный.

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

когда я уверен в своей функции, то я преобразую его в бесконечный цикл:

    for(;;) recursiveFunction(oneParam);