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

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

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

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

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

#define while(true) for(;;)

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


person Chris Cooper    schedule 09.04.2010    source источник
comment
Что такое _1 _ ???   -  person AnT    schedule 10.04.2010
comment
ИСТИНА - 1, ИСТИНА - это определение win32 afaik   -  person smerlin    schedule 10.04.2010
comment
@smerlin: Может быть. Но что он делает в вопросе, в котором вообще не упоминается Win32?   -  person AnT    schedule 10.04.2010
comment
Если это C ++, используйте true. Для C используйте TRUE. Это все.   -  person Steven Sudit    schedule 10.04.2010
comment
Я предполагал, что TRUE будет определено как 1 для использования в качестве псевдобулевого значения.   -  person Chris Cooper    schedule 10.04.2010
comment
@ Стивен Судит: Что общего у TRUE с C? Стандартный макрос для истинного логического результата в C99 по-прежнему true. Откуда взялся TRUE?   -  person AnT    schedule 10.04.2010
comment
Я лично считаю, что for(;;) является более ясной конструкцией. while (true) означает, что вы проверяете true каждый цикл; очевидно, я знаю, что это оптимизировано, но это ненужный код.   -  person meagar    schedule 10.04.2010
comment
Этот макрос не работает, хотя #define EVER ;; использовался в IOCCC .. :)   -  person    schedule 10.04.2010
comment
Я просто подумал, что фраза «бесконечный цикл» вводит в заблуждение, потому что на самом деле мы не имеем в виду бесконечность, поскольку есть еще условие, что цикл разрывается. Вместо этого мы имеем в виду, что это цикл, который имеет сложные условия, выходящие за рамки возможностей встроенных конструкций языка для поддержки цикла. Просто условие не обязательно является выражением, но может быть событием или чем-то в этом роде.   -  person AaronLS    schedule 10.04.2010
comment
Некоторые заголовки, включенные ‹windows.h›, определяют ИСТИНА для типа Windows BOOL. Наверное, отсюда это взялось. Это действительно обычное дело в программировании на Win32.   -  person sblom    schedule 10.04.2010
comment
только не пишите для (;;); или у вас могут быть проблемы   -  person Samuel Carrijo    schedule 10.04.2010
comment
Разве это не макрос для #define while(TRUE) объявления макроса, который принимает один аргумент с именем TRUE, который никогда не используется, поэтому превращает каждый цикл while в вашей программе в бесконечный цикл?   -  person AshleysBrain    schedule 10.04.2010
comment
@Andrey: Стандартный макрос в VS 6.0 - TRUE.   -  person Steven Sudit    schedule 11.04.2010
comment
@ Стивен Судит: Нет. В VS 6.0 нет стандартных макросов. Макрос TRUE поступает из файлов заголовков, связанных с Windows API. Это никак не связано с VS 6.0. И, как я уже сказал, это не имеет ничего общего ни с C, ни с C ++. В C ++ истинный литерал - это просто true (также в VS 6.0), в C89 / 90 такого нет вообще, а в C99 это макрос true. Это относится ко всем компиляторам C / C ++.   -  person AnT    schedule 11.04.2010
comment
@AndreyT: Думаю, ты пытаешься быть более разборчивым, чем полезно. VS 6.0 поставляется с заголовочными файлами Windows SDK, которые включены в StdAfx.h в проект по умолчанию. В этом заголовке есть TRUE #define. Этот #define присутствует в C Windows SDK в течение некоторого времени, до добавления true к языку, поэтому я назвал его C ++, а не C. Теперь, когда я объяснил себя, я действительно не заинтересован в придирках после этого момента.   -  person Steven Sudit    schedule 12.04.2010
comment
Дело в том, что он непереносимый ...   -  person Matthieu M.    schedule 12.04.2010
comment
@ Стивен: Нет ИСТИНЫ, все просто.   -  person GManNickG    schedule 19.04.2010
comment
@anon Тогда просто используйте while(1), хотя я уверен, что вы не были родился орлом.   -  person Mateen Ulhaq    schedule 20.11.2011
comment
Я вижу, что некоторые люди используют goto для бесконечного цикла. Goto самый быстрый?   -  person Rick2047    schedule 14.02.2013
comment
@GManNickG: вы не можете справиться с ИСТИНОЙ. То есть все пользователи, не использующие Windows.   -  person smci    schedule 12.03.2013
comment
На самом деле кто-то спросил, является ли for (;;) быстрее (???), чем while (1). Вера в сообщество программистов снова потеряна.   -  person    schedule 01.07.2013
comment
Никто не указал: for(;;) всего 7 символов, где while(true) равно 11, даже while(1) равно 8. Так что с точки зрения Бешеной разработки приложений мы все должны четко использовать for. Особенно, когда ;; использует ценную домашнюю недвижимость, обычно разбазариваемую QWERTY.   -  person    schedule 31.03.2014
comment
На самом деле #define EVER ;; никогда не использовался в IOCCC, по крайней мере, в выигрышной записи. Когда я впервые изучал C, я действительно использовал #define EVER ;; или, возможно, #define EVER (;;). В то время я подумал, что это очень умно. Я все еще думаю, что это очень умно; Я просто больше не считаю, что это хорошо.   -  person Keith Thompson    schedule 24.07.2014


Ответы (21)


  1. Это не быстрее.
  2. Если вам действительно интересно, скомпилируйте вывод на ассемблере для вашей платформы и посмотрите.
  3. Это не имеет значения. Это не имеет значения. Пишите свои бесконечные циклы, как хотите.
person Ben Zotto    schedule 09.04.2010
comment
Интуитивно оптимизация бесконечного цикла дает возможность бесконечного ускорения. Хорошо, что мы не программируем на интуицию. :-) - person Steven Sudit; 10.04.2010
comment
Полагаю, ты прав. Думаю, я был вовлечен в религиозные дебаты о мелочах. Спасибо, что освободил мою совесть. : D - person Chris Cooper; 10.04.2010
comment
@Steven LOL, это интересно, но тогда учтите, что единственный сценарий, в котором вы действительно достигли этого потенциала бесконечного ускорения, - это когда цикл никогда не прерывается и действительно работает бесконечно, что, вероятно, либо ошибка, либо, если задумано, будет бесконечное ожидание, прежде чем он достигнет этого потенциала. - person AaronLS; 10.04.2010
comment
Я думаю, он пошутил. ;П - person Chris Cooper; 10.04.2010
comment
@Крис. В программировании, как и в жизни, религиозные дискуссии стоят вашего времени только на действительно важные дела. Это не одна из тех вещей. Как видите, у каждого есть любимый способ написать бесконечный цикл. Выберите для себя то, что вам больше всего нравится в мелочах, а затем запустите свой профилировщик для кода, который имеет значение. :) - person Ben Zotto; 10.04.2010
comment
@Steven Sudit: Многие программы для Amiga были разработаны с помощью программирования на Intuition. :) - person bk1e; 10.04.2010
comment
@AaronLS: Ах, но это была бы бесконечность с большей мощностью! (Доказательство того, что я пошел в колледж даром.) - person Steven Sudit; 11.04.2010
comment
Это имело значение, поскольку некоторые ранние компиляторы на некоторых платформах действительно загружали константу и выполняли ее условный переход. Что в те дни имело значение аппаратное обеспечение. - person peterchen; 21.11.2011
comment
Я пишу свои инфинитивные циклы с помощью GOTO - person meh; 25.11.2012
comment
Это важно для людей. Почему не следует писать while (2) - person Buge; 25.07.2014
comment
Я использую for (;;), поскольку while (true) генерирует предупреждение о постоянном условном выражении. - person paulm; 03.10.2014

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

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

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

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

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

person jalf    schedule 09.04.2010
comment
+1 за избежание предупреждений. Но что касается ясности, то я нахожу ее более ясной, чем в данном контексте. Думаю, этот аспект сводится к личным предпочтениям. - person Tim; 10.04.2010
comment
Ага, предпочтение и привычка. Если вы не привыкли видеть for(;;), это явно будет выглядеть странно. Но я бы рекомендовал попытаться привыкнуть к нему, потому что это распространенная идиома, и вы снова столкнетесь с ней. ;) - person jalf; 10.04.2010
comment
Я уверен, что столкнусь снова, но это не значит, что это хорошая практика = P. Я согласен с Тимом в том, что while более показательно, потому что for обычно используется, когда вы хотите сделать что-то определенное количество раз. Как сказал Джальф, для (;;) нет условия. почему никакое условие не может быть таким же, как новое условие? Если я сказал делать это ни при каких условиях, это значит, НИКОГДА НЕ ДЕЛАЙТЕ ЭТОГО. В любом случае, это только мое мнение. знак равно - person Chris Cooper; 10.04.2010
comment
У него нет условия: это безусловный цикл. И я действительно хочу делать что-то определенное количество раз. Это число просто бесконечность. Чем while лучше? Обычно вы используете это до изменения условия. И этого никогда не случится. Меня не волнует, оценивается ли 1 == 1, 42> 0 или TRUE как истинное. Все это лишь окольные способы сказать «продолжай». Все они могут быть помещены в цикл while для достижения того же самого. Но когда у нас уже есть конкретная форма цикла для этого, зачем прыгать через все эти обручи? - person jalf; 10.04.2010
comment
@jalf: есть ли обстоятельства, при которых вы могли бы использовать цикл while(condition), учитывая, что for(;condition;) делает то же самое? В защиту while(true) он явно заявляет, что условие продолжения всегда выполняется, т.е. всегда продолжается. for(;;) неявно говорит то же самое из-за специального языкового правила, согласно которому исключение условия означает всегда продолжать. Логически это могло так же легко означать всегда прерывание, но, конечно, нулевое время цикла намного менее полезно, чем цикл навсегда. Или вообще не разрешили. Так что это особая идиома, какую бы вы ни использовали. - person Steve Jessop; 10.04.2010
comment
Чтобы заявить о своем интересе, я обычно пишу while(true), но я не думаю, что один из них более ясен, удобочитаем или проще, чем другой, поскольку оба они совершенно ясны. Я хочу написать loop { ... } или, может быть, { ... ; continue; }, но неважно. Я был бы склонен избегать всего, что приводит к таким утверждениям, как будто я делаю это количество раз, равное бесконечности, потому что у меня есть степень по математике, и это просто болезненно ;-) - person Steve Jessop; 10.04.2010
comment
Комментарий jalf о том, что это идиоматично, - действительно ответ здесь. Он обычно используется для бесконечного цикла просто потому, что это обычно используемый способ написания бесконечного цикла в C. Не обязательно быть веской причиной для идиомы - это просто самоусиливающееся соглашение. - person caf; 10.04.2010
comment
@caf: хороший момент. Кодовая обезьяна видит, код обезьяна делает. Тем не менее, обнадеживает то, что jalf видит преимущества, выходящие за рамки простого знакомства :-) - person Steve Jessop; 10.04.2010
comment
Однако культурные условности важны - они позволяют нам более эффективно общаться. - person caf; 10.04.2010
comment
@Steve: Я не понимаю, зачем мне когда-либо использовать for(;condition;). Вот что такое цикл while for. Но, как я уже сказал, с бесконечным циклом я действительно не хочу, чтобы компилятор сравнивал любое условие. Наивно, что с помощью цикла while ему пришлось бы проверять true каждую итерацию (очевидно, что даже самый тупой компилятор не стал бы этого делать, но меня беспокоит этот принцип. Мне кажется, что он задает слишком много значений вашего кода), а с for(;;) вы буквально говорят, что нет условий для проверки. Просто зацикливайтесь. Я считаю его ближайшим эквивалентом твоего воображаемого loop {...} - person jalf; 10.04.2010
comment
Но, на всякий случай, я не сильно в этом уверен. У меня нет абсолютно никаких проблем с просмотром while(true) в коде, с которым мне приходится работать, и я думаю, что оба они прекрасно читаются. Я просто объясняю, почему я думаю, что for(;;) предпочтительнее. - person jalf; 10.04.2010
comment
Справедливо. Я просто спросил, потому что вы сказали, что у нас уже есть конкретная форма цикла для этого, поэтому мне было интересно, придерживаетесь ли вы того же взгляда, что и Go, это все, что нам нужно. Очевидно, нет :-) - person Steve Jessop; 10.04.2010
comment
На самом деле они ничего не удалили, кроме как ... пока, просто объединили это. Все параметры для for необязательны, поэтому в Go бесконечный цикл равен for { ... }. for <condition> { ... } эквивалентен циклу while, есть обычный цикл for с тремя предложениями и, наконец, for i := range <sequence> { ... } - цикл foreach. Имеет смысл, хотя я использовал Go лишь немного, так что я все еще думаю о том, что одно и то же ключевое слово используется для всего ;-) - person Steve Jessop; 10.04.2010
comment
Ваш компилятор отстой, если while(true) выдает предупреждение. - person Albert; 16.07.2010
comment
@Albert: Разработчики Microsoft Visual C ++, похоже, не разделяют вашего мнения. - person sharptooth; 25.01.2012
comment
Я не совсем знаю почему, но для меня for(;;) кратко представляет типичную порочность C (и C ++ по наследству). Больше, чем ужасное обращение с массивами, даже больше, чем пренебрежительное отношение к числовому программированию, и даже больше, чем ~ 14 страниц обобщенного неопределенного поведения в стандарте C, и, что еще хуже, нас так смущает огромное количество UB, которое существует в C ++, что мы даже не будем обобщать его в приложении к стандарту C ++. - person David Hammen; 26.07.2014
comment
Мой опыт показывает, что ответы, содержащие for(;;), получают отрицательные голоса в Stack Overflow в тех случаях, когда тот же ответ с while(true) будет приносить положительные голоса. - person Dawood ibn Kareem; 04.10.2018
comment
@DawoodibnKareem Полагаю, мне придется проголосовать против некоторых while(true) вопросов ... ;-) - person Andrew Henle; 05.01.2021

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

person ta.speot.is    schedule 09.04.2010
comment
0, 1 и бесконечность являются допустимыми магическими числами, расширение 0 и 1 до false и true не является потерей. true является магическим числом не больше, чем for является волшебным ключевым словом или что for(;;) использует подразумеваемую магическую бесконечность. (while (42) действительно мерзость.) - person ; 10.04.2010
comment
Касательная: один из моих преподавателей компьютерных наук сказал, что в программировании всего три числа: 0, 1 и n. все остальное называется магическим числом. - person Ben Zotto; 10.04.2010
comment
За исключением VB, где приведение true к целому числу дает -1. - person Kibbee; 10.04.2010
comment
while (42) является самым крутым, не дает другого результата относительно while (1), while (true) или while (! 0) и имеет философское значение. Я полагаю, for(;;) в любом случае разбирается быстрее, чем другие - person ShinTakezou; 10.06.2010
comment
@ShinTakezou намного лучше #define LIFE 42 while (LIFE) :) - person mr5; 01.07.2013
comment
ну while(true) тоже не содержит числа. и for (;;) не является ключевым словом - person RiaD; 26.07.2014
comment
@RiaD Разбирайте фразу как только одно ключевое слово. - person ta.speot.is; 27.07.2014
comment
А что насчет for(0xEFAAAAAA)? - person Timmos; 10.10.2017

Благодаря Деннису Ричи

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

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

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

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

person Mark Harrison    schedule 10.04.2010
comment
Да, именно так вы узнаете, что кто-то выучил C у K&R, как это следует выучить. Всякий раз, когда я вижу while(TRUE), я подозреваю, что программист - новичок в C или выучил C из книги для чайников. - person Kristopher Johnson; 20.05.2010
comment
Я слышал, что эти новички тоже используют новый стиль определения функций. - person Justin; 15.10.2014
comment
IIRC, в исходном компиляторе C Ричи, for(;;) действительно генерировал меньше кода, чем while(1), и поэтому был предпочтительным (поскольку в те дни они много заботились о размере кода). - person Steve Summit; 13.01.2021

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

Если вам интересно, вот что дает мне 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
person Matthew Flaschen    schedule 09.04.2010
comment
Сомневаюсь, что быстрее даже в режиме отладки. - person Steven Sudit; 10.04.2010
comment
for_infinite быстрее; На 2 символа меньше до puts. - person Dave Jarvis; 10.04.2010

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

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

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

person Boann    schedule 27.08.2012
comment
Спасибо за Ваш ответ! Я думаю, что это первый ответ, который объективно показывает, что for (;;) лучше. - person Chris Cooper; 04.09.2012
comment
Не думаю, что мне когда-либо понадобится писать правильный код на C, C ++, JavaScript, Java и C #. Это разные языки. - person Keith Thompson; 24.07.2014
comment
@KeithThompson - это не о написании кода, правильного для многих языков; я думаю, что речь идет о том, чтобы избежать неправильного толкования между разработчиками с разным опытом. - person Mauro Sampietro; 25.07.2014
comment
@sam: И while (1), и for (;;) являются общими идиомами для бесконечных циклов в C. Любой, кто читает программу на C и не понимает ни одной из них, скорее всего, будет иметь проблемы с остальной частью кода. Не стоит писать код C, который может быть легко прочитан тем, кто не знает C. - person Keith Thompson; 25.07.2014
comment
@KeithThompson Хотя компетентный читатель C определенно должен быть знаком с обеими идиомами, это также может быть полезно, если автор - программист-полиглот. На моей последней работе я ежедневно работал с JS, ActionScript и PHP, и унификация способа написания кода (где это имеет смысл) может ускорить программирование и упростить обслуживание. - person Ionoclast Brigham; 26.07.2014
comment
Это отличная причина переключиться на for, так как я был обожжен самими вещами в этом посте. - person jedd.ahyoung; 11.09.2014

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

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

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

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

person Michael Burr    schedule 09.04.2010

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

#define EVER ;;

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

for (EVER)
{
    /* blah */
}
person rmeador    schedule 09.04.2010
comment
Я тоже это видел; но это не повод для его предпочтения. Как сопровождающий, вам все равно придется проверять определение макроса, чтобы быть уверенным, что он делает то, что вы ожидаете, тогда как исходный код был достаточно ясным. В RTOS VxWorks есть макрос, FOREVER определенный for(;;), но это не лучше. Макросы IMO не следует использовать для «изобретения» нового языка. - person Clifford; 10.04.2010
comment
На самом деле цель макросов в некоторых языках - изобрести новый синтаксис. Но независимо от того, «за (КОГДА-ЛИБО)» в C / C ++ - это отвратительно. - person Dan Olson; 10.04.2010
comment
Некоторые люди делают забавные вещи, например, если им нравится Паскаль, они говорят #define BEGIN { и #define END }. Я даже видел #define DONKEYS_FLY (0), чтобы они могли сказать if DONKEYS_FLY .... Кто сказал, что программное обеспечение скучно? - person Mike Dunlavey; 10.04.2010
comment
Скопировано из моего комментария к вопросу, где я указал, что он использовался только для юмористических целей / обфускации. Не делайте этого в реальном коде. - person ; 11.04.2010
comment
В Калифорнии, я полагаю, вам нужно #define for (;;) LIKE_FOREVER - person Martin Beckett; 19.04.2010
comment
Не удержался: #define never while(0) и #define always - person alfC; 02.10.2013
comment
Почему люди просто не пишут #define loop for(;;)? - person SOFe; 08.04.2020
comment
@SOFe Потому что это выглядит забавно, если вы напишете for(ever). - person xiaoyu2006; 01.11.2020

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

start:
/* BLAH */
goto start;
person bungle    schedule 09.04.2010
comment
... который должен генерировать идентичный вывод в руках любого разумного компилятора. - person Ben Zotto; 10.04.2010
comment
+1! Это не устраняет многочисленные недостатки goto, но, если алгоритм, который вы пытаетесь реализовать, исходит из блок-схемы, это наиболее прямой перевод. - person Edmund; 10.04.2010
comment
Я лично придерживаюсь утилитарного взгляда на goto. Хищников нет. Хищники - это люди. И именно люди начали использовать goto для создания спагетти-кода. Кроме того, собранный вывод цикла выглядит примерно так же. В наборах инструкций для компьютеров нет концепций «пока» или «пока», просто прыгайте. - person josaphatv; 13.10.2013
comment
никогда не использовать goto - person Edward Karak; 02.02.2014
comment
В goto действительно хорошо то, что вам не нужно беспокоиться о том, что кто-то добавит break, чтобы сделать ваш цикл менее бесконечным. (если, конечно, вы уже не находитесь внутри другого while или for цикла ...) - person ; 31.03.2014

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

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

person Jason Williams    schedule 09.04.2010
comment
Это зависит от вашего языка. for(;;) - традиционный способ сделать это в C и C ++. while(true), похоже, является соглашением в C #, Java и других языках. Ваш пробег может отличаться. - person Billy ONeal; 10.04.2010
comment
Но тот, кто не очень знаком с C или C ++, будет легче читать while (true), а кто-то, знакомый с ними, тоже поймет его, поэтому он более читабелен. - person David Espart; 10.04.2010
comment
Да, и кто-то, кто не очень знаком с C или C ++, может найти STRING_SCAN_FORMATTED более читабельным, чем sscanf, но вы не видите, чтобы кто-то поместил #define STRING_SCAN_FORMATTED sscanf в начало своего кода. - person ta.speot.is; 10.04.2010
comment
Я бы сказал, что идиоматический способ сделать это должен быть наиболее читаемым для вашего разработчика. В противном случае вам действительно нужны лучшие разработчики. - person jalf; 10.04.2010
comment
@despart: Если кто-то недостаточно знаком с C ++, чтобы распознать эту идиому таким, какая она есть, то ему нужно держаться подальше от моей кодовой базы. - person Billy ONeal; 10.04.2010
comment
Я согласен с тем, что идиоматический способ должен быть наиболее читаемым. Вот почему идиоматические способы всегда нужно оспаривать и менять по мере развития языков и практик. Потребовались годы, чтобы ужасный идиоматический стиль кодирования K&R был заменен современным, более читаемым стилем, но это все же произошло. - person Jason Williams; 10.04.2010

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

person James McLeod    schedule 09.04.2010
comment
Да, и я думаю, что некоторые компиляторы предупреждают о while (true) по той же причине, что и о if (true). - person Steven Sudit; 10.04.2010

while(true)

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

for(;;)

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

person Michael    schedule 10.04.2010
comment
какую версию Visual Studio вы используете? В 2008 году я не получаю этого предупреждения даже на уровне предупреждения 4. - person Jörgen Sigvardsson; 05.12.2010

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

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

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

person SylvanBlack    schedule 02.10.2013
comment
На самом деле это очень хороший момент! Без оптимизации даже современные компиляторы будут отличаться несколькими инструкциями. - person ; 31.03.2014

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

Я найду, если быстрее набрать «пока (ИСТИНА)».

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

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

(Мой тест TypingTest.com = 136 слов в минуту)

person Mark Rejhon    schedule 09.04.2010
comment
Я считаю, что OP имел в виду скорость выполнения, а не скорость набора. - person ; 10.04.2010
comment
Я знаю. Просто пришлось прикрыть и эту базу. - person Mark Rejhon; 10.04.2010
comment
s / личные предпочтения / индивидуальные привычки / - person SamB; 10.04.2010
comment
@SamB: Прокомментируйте и проголосуйте за s ///. xD И да, хотя я предположил, что это может быть связано со скоростью выполнения, я не знал фактического ответа. Если бы это было так, я был бы счастлив. - person Chris Cooper; 10.04.2010
comment
Запустите time head -10 >/dev/null, введите каждое по 10 раз и измерьте результаты. Бьюсь об заклад, ты будешь быстрее for(;;), если не обманешь. Я был примерно на 14%. - person PSkocik; 26.09.2015

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

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

Вам должно быть все равно?

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

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

person Mike Dunlavey    schedule 10.04.2010
comment
Как часто вы видите людей, которые предпочитают ++i i++? - person Dennis Zickefoose; 10.04.2010
comment
@Dennis Zickefoose: разница между ++i и i++ потенциально может быть значительной, если i является экземпляром класса, а не встроенным, и компилятор не применяет тривиальную оптимизацию. Совет: приобретите привычку, чтобы она не зацепила вас, когда она имеет значение. - person Clifford; 10.04.2010
comment
Отличие ++i vs i++ в том, что вам ничего не стоит сделать оптимизацию. Правда, в большинстве случаев это не имеет абсолютно никакого значения, но их одинаково легко набирать, так почему бы не предпочесть потенциально наиболее эффективные по умолчанию? И я полагаю, что то же самое применимо и здесь. Если один был немного быстрее другого, почему не выбрать более быстрый? Что мы потеряем, сделав это? Оба варианта довольно легко читать и печатать. - person jalf; 10.04.2010
comment
@Clifford: @jalf: Я пытаюсь похудеть :-), и у меня есть стрижки, но аргументы в форме: вы бы сэкономили микроцент, так почему бы не сделать это? не производите на меня особого впечатления, потому что для игнорирования этого достаточно микропричины, например, солнце светит, так зачем об этом думать? - person Mike Dunlavey; 10.04.2010
comment
@Dennis Zickefoose: Ты прав. Я часто это вижу на SO, и комментарий Клиффорда верен. Кроме того, есть кое-что, чего я не очень вижу в SO, а именно то, как выполнять макрооптимизацию, например ускорение в 43 раза: stackoverflow.com/questions/926266/. Поэтому я задаюсь вопросом о наших приоритетах. - person Mike Dunlavey; 10.04.2010
comment
@Clifford: Хотя я полностью понимаю вашу точку зрения (и как пилот, подобные рассуждения очень важны), в программировании мне всегда приходится переходить к конкретным деталям. Например, в тех немногих случаях, которые я видел, когда замена ++ и i приводила к значительному изменению производительности, поскольку i был экземпляром класса, он приводил к гораздо большему изменению производительности, чтобы заменить i на целое число. Вы не всегда можете так поступить? Возможно, но здесь мы становимся действительно гипотетическими, и в любом случае можно положиться на макрооптимизацию, чтобы выявить проблему. - person Mike Dunlavey; 10.04.2010
comment
@Mike: Да, но это сравнение яблок с апельсинами. Стрижка требует времени и, возможно, даже денег. Я согласен, что это такая микрооптимизация, что это не имеет особого значения. Но это также ничего нам не стоит. если я могу выбрать, идти налево или направо, и расстояние такое же, местность такая же, все то же самое, за исключением того, что левый путь имеет небольшое микроскопическое преимущество, почему бы не пойти налево ? Вы правы, это не впечатляющий аргумент. Но когда стоимость буквально равна нулю, я не вижу причин отдавать предпочтение менее оптимальному маршруту. - person jalf; 10.04.2010
comment
Я действительно не был с тобой не согласен. Я согласен, что вам все равно не важно, что используется, но последовательность стиля важна. Если два варианта одинаково читаемы, вы также можете выбрать стиль, который сэкономит вам три тактовых цикла. Если светит солнце или вы чувствуете, что while(1) более информативен, чем for(;;), используйте его, независимо от потерянных тактов. Даже если этот сегмент кода окажется проблематичным, это, вероятно, будет не из-за выбранного вами типа цикла. По аналогичной логике я всегда использую i++ в моем собственном коде, потому что это имеет для меня больше смысла. - person Dennis Zickefoose; 10.04.2010
comment
@Mike Dunlavey: ускорение x43? Попробуйте CUDA. - person Clifford; 10.04.2010
comment
@Dennis Zickefoose: Кстати, я редко могу заставить себя написать ++ i в любом случае ;-); просто слишком уродливо! И если вы вызвали переменную i, и она не была простой int, вероятно, существуют более серьезные проблемы со стилем кодирования! - person Clifford; 11.04.2010
comment
@ Клиффорд: Я решительно согласен. Мне также очень скучно, потому что я не нашел юмористического способа указать на то, насколько удивительно, что инженеры по аппаратному обеспечению ломают себе голову, делая машины быстрее и дешевле, в то время как мы, программисты, вместо того, чтобы устранять ненужные циклы, говорим: «Зачем беспокоиться?» Просто добавь больше оборудования. У меня есть мысленный образ воспитанной скаковой лошади, тащащей 400-фунтового жокея, или 10 раз кружащей по трассе, чем можно было бы сделать один раз, или совершающей большие объездные пути. - person Mike Dunlavey; 11.04.2010
comment
С пре- и пост-инкрементом вы должны позаботиться о том, какой из них будет использоваться. Разница изменит функцию программы, а не только ее производительность. Если одно из них не имеет для вас смысла, то во что бы то ни стало избегайте его. В этом случае лучше переключиться на foo = foo + 1; и сохранить его в отдельном операторе. (И на всякий случай даже не думайте об использовании тройного оператора ?:) Конечно, это подразумевает предпочтительную форму бесконечного цикла: for(unsigned int i=0; i<0; i = i + 1); - person ; 31.03.2014

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

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

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

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

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

person Clifford    schedule 09.04.2010
comment
ИСТИНА может не быть #define ИСТИНА 1, но любая база кода, в которой while(TRUE) оценивается как while(0), вряд ли выиграет от for(;;). - person Justin; 15.10.2014
comment
@Justin: Я согласен, это было бы действительно извращенно, и это не самый сильный из трех аргументов, но Бьярн Стауструп использует аналогичный аргумент, чтобы избежать макроса NULL в C ++. while(true) следует отдавать предпочтение в любом случае. В C ++ bool зарезервировано, а в C определено в C stdbool.h (что делает его менее безопасным в C). for(;;) устраняет все сомнения. - person Clifford; 17.10.2014

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

Яснее, чем:

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

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

person Armada    schedule 23.02.2013
comment
Это чертовски плохой код, вместо сна следует использовать таймер, так что это плохой пример - person ST3; 08.04.2014
comment
@ ST3 - Да, ты прав. Мой код ужасен. В следующий раз, когда я сделаю бесконечный цикл, я должен постараться. - person Armada; 13.05.2014
comment
@ ST3 Просто из интереса, как можно кодировать приведенный выше пример с помощью таймера? - person Armada; 09.03.2015
comment
@Frammo - зависит от вашей ОС, но обычно что-то вроде timerService.scheduleRepeating (50, [] () { /* lots of code */ }); - person Periata Breatta; 11.11.2016
comment
Нет ничего чистого в вызове такой функции, как сон, внутри такого цикла for - person Greg; 14.10.2017
comment
OMG, timerService.scheduleRepeating (50, [] () {}) просто ооочень легче набирать и понимать, чем спать (50). - person Cool Javelin; 09.12.2018
comment
Это не эквивалент. Когда в цикле есть continue, цикл for засыпает, но не цикл while. - person 12431234123412341234123; 05.01.2021

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

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

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

person Thomas Matthews    schedule 09.04.2010
comment
Если компилятор генерирует для них другой код, пора отказаться от компилятора и взять его за последние два десятилетия. - person GManNickG; 10.04.2010
comment
время выполнения циклов не имеет большого значения, поскольку эти циклы продолжаются вечно - это звучит так неправильно для меня ... - person Blindy; 10.04.2010
comment
@Blindy - поскольку это неверно, вызывает беспокойство доля времени выполнения, потраченная на обработку логики цикла, или количество логики цикла на единицу полезной работы, ни тому, ни другому не помогает бесконечность цикла - person Ben Voigt; 10.04.2010

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

person nik    schedule 10.04.2010
comment
Я забочусь о скорости. Особенно, если есть оптимизация, которая бесконечно повлияет на мой код. - person Ekrem Dinçel; 24.03.2020

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

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

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

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

    for(;;) recursiveFunction(oneParam);
person Ignacio Cortorreal    schedule 01.07.2013
comment
В первом цикле есть синтаксическая ошибка (отсутствует точка с запятой). - person Jens; 27.05.2016
comment
Ха! Тем самым демонстрируя обратную сторону for (;;);) - person Andrew; 19.10.2016

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

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

Ваше определение не сработает. Однако вы МОЖЕТЕ (но не должны) это делать:

#define repeat for(;;)

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

Но на самом деле, НЕ делайте этого ...

person klutt    schedule 05.01.2021