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

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

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

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

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

#define while(true) for(;;)

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

Ответ 1

  • Это не быстрее.
  • Если вам действительно интересно, скомпилируйте с выходом ассемблера для своей платформы и посмотрите, чтобы увидеть.
  • Это не имеет значения. Это никогда не имеет значения. Напишите свои бесконечные петли, как вам нравится.

Ответ 2

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

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

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

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

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

Ответ 3

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

Ответ 4

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

Если вам интересно, вот что gcc 4.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

Ответ 5

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

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

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

  • Ваш #define не будет работать, поскольку предмет # define'd должен выглядеть как идентификатор C.

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

Ответ 6

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

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

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

Ответ 7

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

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

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

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

Ответ 8

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

#define EVER ;;

Это позволяет им написать это:

for (EVER)
{
    /* blah */
}

Ответ 9

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

start:
/* BLAH */
goto start;

Ответ 10

while(true)

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

for(;;)

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

Ответ 11

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

Ответ 12

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

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

Ответ 13

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

int x = 0;

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

    printf("%d", x);
}

Если вы построите его в режиме отладки (без какой-либо оптимизации (/Od)), демонстрация показывает явное различие. В true есть дополнительные инструкции для 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)  

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

Ответ 14

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

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

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

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

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

Ответ 15

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

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

Вам все равно?

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

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

Ответ 16

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

Яснее, чем:

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

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

Ответ 17

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

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

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

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

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

Ответ 18

Цикл "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

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

и кто заботится о том, какой из них быстрее, если есть

Ответ 20

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

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

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

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

    for(;;) recursiveFunction(oneParam);