Является ли "for (;;)" быстрее, чем "while (TRUE)"? Если нет, то почему люди используют это? - PullRequest
156 голосов
/ 10 апреля 2010
for (;;) {
    //Something to be done repeatedly
}

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

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

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

#define while(true) for(;;)

См. Также: Что быстрее: while (1) или while (2)?

Ответы [ 20 ]

11 голосов
/ 02 октября 2013

Оба должны быть одинаковыми, если ваш код оптимизирован компилятором. Чтобы объяснить, что я имею в виду под оптимизацией, вот пример кода, написанного в MSVC 10:

int x = 0;

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

    printf("%d", x);
}

Если вы строите его в режиме отладки ( без какой-либо оптимизации (/ Od) ), разборка показывает явную разницу. Внутри while.

есть дополнительные инструкции для условия true.
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)  

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

11 голосов
/ 10 апреля 2010

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

11 голосов
/ 10 апреля 2010
while(true)

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

for(;;)

является предпочтительным.

9 голосов
/ 10 апреля 2010

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

Я найду, если быстрее набрать "while (TRUE)".

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

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

(мой тест TypingTest.com = 136 WPM)

6 голосов
/ 10 апреля 2010

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

ОДНАКО - Просто предположим, что это имело значение. Предположим, что одна из них взяла еще 3 инструкции за итерацию.

Вас это волнует?

ТОЛЬКО если то, что вы делаете внутри цикла, является почти ничем , что почти никогда имеет место.

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

5 голосов
/ 24 февраля 2013
for(;;Sleep(50))
{
    // Lots of code
}

Является ли яснее, чем:

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

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

5 голосов
/ 10 апреля 2010

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

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

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

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

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

4 голосов
/ 10 апреля 2010

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

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

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

2 голосов
/ 01 июля 2013

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

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

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

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

    for(;;) recursiveFunction(oneParam);
2 голосов
/ 10 апреля 2010

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

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

...