Длинная версия ...
Сотрудник заявил сегодня, увидев мое использование while (1)
в сценарии Perl, который for (;;)
работает быстрее. Я утверждал, что они должны быть такими же, надеясь, что переводчик оптимизирует любые различия. Я установил скрипт, который будет запускать 1 000 000 000 для итераций цикла и столько же циклов while и записывать время между ними. Я не мог найти никакой заметной разницы. Мой коллега сказал, что профессор сказал ему, что while (1)
он сравнивает, 1 == 1
а for (;;)
нет. Мы повторили тот же тест с 100-кратным числом итераций с C ++, и разница была незначительной. Однако это был графический пример того, насколько быстрее может быть скомпилированный код по сравнению с языком сценариев.
Укороченная версия...
Есть ли какая - либо причина предпочитает while (1)
больше , for (;;)
если вам нужен бесконечный цикл , чтобы вырваться из?
Примечание: если это не ясно из вопроса. Это была просто веселая академическая дискуссия между парой друзей. Я знаю, что это не супер важная концепция, которую должны мучить все программисты. Спасибо за все замечательные ответы, которые я (и я уверен, что другие) узнали несколько вещей из этой дискуссии.
Обновление: вышеупомянутый сотрудник взвесил ответ ниже.
Цитируется здесь на случай, если его похоронят.
Это пришло от ассемблера AMD. Он заявил, что программисты на Си (люди) не понимают, что их код имеет недостатки. Однако сегодня он сказал, что компиляторы gcc очень хороши и выводят таких людей, как он, из бизнеса. Он сказал, например, и рассказал мне о
while 1
противfor(;;)
. Сейчас я использую его по привычке, но gcc и особенно интерпретаторы будут выполнять одну и ту же операцию (скачок процессора) в течение обоих дней, так как они оптимизированы.
источник
Ответы:
В Perl они дают одинаковые коды операций:
Аналогично в GCC:
Поэтому я думаю, что ответ таков: они одинаковы во многих компиляторах. Конечно, для некоторых других компиляторов это не обязательно так, но есть вероятность, что код внутри цикла будет в несколько тысяч раз дороже самого цикла, так кого это волнует?
источник
Используя GCC, они оба, похоже, компилируются на одном языке ассемблера:
источник
Нет особой причины предпочитать одно другому. Я думаю, что это
while(1)
особенноwhile(true)
читабельноfor(;;)
, но это мое предпочтение.источник
forever
это его собственный токен.Там нет разницы по стандарту. 6.5.3 / 1 имеет:
И 6.5.3 / 2 имеет:
Итак, в соответствии со стандартом C ++ код:
точно так же, как:
источник
Компилятор Visual C ++ используется для предупреждения
(постоянное выражение), но не для
Я продолжил практику предпочтения
for (;;)
по этой причине, но я не знаю, по-прежнему ли это делает компилятор в наши дни.источник
for(;;)
на один символ меньше, если вы хотите пойти в этом направлении, чтобы оптимизировать вещи.источник
Turbo C с этим старым компилятором
for(;;)
приводит к более быстрому кодуwhile(1)
.Сегодня компиляторы gcc, Visual C (я думаю, почти все) хорошо оптимизируются, а процессоры с частотой 4,7 МГц используются редко.
В те дни a
for( i=10; i; i-- )
был быстрее, чемfor( i=1; i <=10; i++ )
, потому что сравнениеi
равно 0, приводит к условному переходу CPU-Zero-Flag. И Zero-Flag был изменен с последней операцией декремента( i-- )
, никакой дополнительной операции cmp не требуется.а вот
for(i=1; i<=10; i++)
с дополнительным cmpl:источник
Для всех людей, утверждающих, что вы не должны использовать неопределенные циклы while, и предлагать глупые вещи, такие как использование open goto 's (серьезно, ой)
На самом деле не может быть эффективно представлен любым другим способом. Не без создания выходной переменной и выполнения черной магии для ее синхронизации.
Если у вас есть склонность к более сложному синтаксису, используйте что-то вменяемое, что ограничивает область действия.
В конечном счете, скорость не так важна
Беспокоиться о том, насколько эффективны различные циклические конструкции, - огромная трата времени. Преждевременная оптимизация насквозь. Я не могу вспомнить ни одной ситуации, в которой я когда-либо видел, чтобы профилирующий код нашел узкие места в моем выборе конструкции цикла.
Обычно это как цикла и как цикла.
Вы должны «оптимизировать» читабельность и лаконичность, и написать все, что лучше при объяснении проблемы, следующему бедному обманщику, который найдет ваш код.
Если вы используете трюк "goto LABEL", о котором кто-то упоминал, и я должен использовать ваш код, будьте готовы спать с одним открытым глазом, особенно если вы делаете это более одного раза, потому что такого рода вещи создают ужасно спагетти-код.
То, что вы можете создать код для спагетти, не означает, что вы должны
источник
От Страуструпа, TC ++ PL (3-е издание), §6.1.1:
Я предпочитаю
for (;;)
.источник
Если компилятор не выполняет оптимизацию,
for(;;)
он всегда будет быстрее, чемwhile(true)
. Это связано с тем, что оператор while оценивает условие каждый раз, а оператор for - безусловный переход. Но если компилятор оптимизирует поток управления, он может генерировать некоторые коды операций. Вы можете прочитать код разборки очень легко.PS вы могли бы написать бесконечный цикл, как это:
источник
Я слышал об этом однажды.
Это пришло от ассемблера AMD. Он заявил, что программисты на C (люди) не осознают, что их код неэффективен. Однако сегодня он сказал, что компиляторы gcc очень хороши и выводят таких людей, как он, из бизнеса. Он сказал, например, и рассказал мне о
while 1
противfor(;;)
. Сейчас я использую его по привычке, но gcc и особенно интерпретаторы будут выполнять одну и ту же операцию (скачок процессора) в течение обоих дней, так как они оптимизированы.источник
В оптимизированной сборке скомпилированного языка не должно быть заметного различия между ними. Никто не должен выполнять какие-либо сравнения во время выполнения, они просто будут выполнять код цикла, пока вы не выйдете из цикла вручную (например, с помощью a
break
).источник
Я удивлен , что никто должным образом не тестировался в
for (;;)
сравненииwhile (1)
с Perl!Поскольку perl является интерпретируемым языком, время запуска сценария perl состоит не только из фазы выполнения (которая в этом случае одинакова), но и из фазы интерпретации перед выполнением. Обе эти фазы должны быть приняты во внимание при сравнении скорости.
К счастью, в Perl есть удобный модуль Benchmark, который мы можем использовать для реализации теста:
Обратите внимание, что я тестирую две разные версии бесконечного цикла for: одну, которая короче, чем цикл while, и другую, которая имеет дополнительный пробел, чтобы сделать его такой же длины, как цикл while.
На Ubuntu 11.04 x86_64 с Perl 5.10.1 я получаю следующие результаты:
Цикл while явно выиграл на этой платформе.
На FreeBSD 8.2 x86_64 с Perl 5.14.1:
Хотя цикл здесь тоже победитель.
На FreeBSD 8.2 i386 с Perl 5.14.1:
Удивительно, но цикл for с дополнительным пробелом - самый быстрый выбор здесь!
Мой вывод заключается в том, что цикл while следует использовать на платформе x86_64, если программист оптимизирует скорость. Очевидно, что для оптимизации пространства следует использовать цикл for. Мои результаты, к сожалению, неубедительны в отношении других платформ.
источник
Benchmark
имеет свои ограничения и не может использоваться для отличия быстрого от медленного, если результаты находятся в пределах 7% друг от друга. Кроме того, вы не испытали разницу междуfor
иwhile
петлями , потому что каждый суб будетdie
до достижения самих петель. И с каких это пор количество пробелов имеет значение для интерпретатора Perl? Извините, но анализ крайне некорректен.die
моем коде есть, потому что я собираюсь проверить только разницу во времени компиляции . Как уже отмечали другие, полученный байт-код идентичен, поэтому нет смысла проверять это. Удивительно, но количество пробелов в этом случае незначительно меняет мои тестовые среды. Это может иметь какое-то отношение к тому, как персонажи оказываются выровненными в памяти или что-то подобное ...Benchmark
неубедительны. Не верьте этой разнице в 1%!-60
запускает тест в течение 60 секунд.Теоретически, полностью наивный компилятор может хранить литерал '1' в двоичном коде (тратить пространство) и проверять, равен ли 1 == 0 на каждой итерации (тратить время и больше места).
В действительности, однако, даже с оптимизацией «без» компиляторы все равно будут сводить оба к одному и тому же. Они также могут выдавать предупреждения, поскольку это может указывать на логическую ошибку. Например, аргумент
while
может быть определен где-то еще, и вы не понимаете, что это константа.источник
Я удивлен, что никто не предложил более прямую форму, соответствующую желаемой сборке:
источник
{ forever: do stuff; goto forever; }
)while(1)
это идиома, заfor(;;)
которую признают большинство компиляторов.Я был рад видеть, что Perl
until(0)
тоже распознает .источник
Подводя итог дебатам
for (;;)
противwhile (1)
, очевидно, что первый был быстрее во времена старых неоптимизирующих компиляторов, поэтому вы склонны видеть его в более старых базах кода, таких как комментарии к исходному коду Lions Unix, однако в эпоху оптимизации компиляторы эти выгоды оптимизируются в сочетании с тем, что последний легче понять, чем первый, я считаю, что это было бы более предпочтительным.источник
Просто наткнулся на эту ветку (хотя и опоздал на несколько лет).
Я думаю, что нашел реальную причину, по которой «for (;;)» лучше, чем «while (1)».
в соответствии со «стандартом кодирования barr 2018»
в основном это не проблема скорости, а проблема читабельности. В зависимости от шрифта / печати кода число один (1) через некоторое время может выглядеть как строчная буква l.
т.е. 1 против л. (в некоторых шрифтах они выглядят одинаково).
Так что while (1) может выглядеть как цикл while, зависящий от переменной L.
Хотя (true) также может работать, но в некоторых старых случаях C и встроенного C true / false еще не определены, если не включен stdbool.h.
источник
l
, а не та,1
и онаl
может выглядеть аналогично.Я думаю, что оба одинаковы с точки зрения производительности. Но я бы предпочел while (1) для удобства чтения, но я спрашиваю, зачем вам нужен бесконечный цикл.
источник
Они одинаковые. Есть гораздо более важные вопросы для размышления.
Моя точка зрения, которая подразумевалась, но явно не указана выше, заключается в том, что приличный компилятор будет генерировать одинаковый код для обеих форм цикла. Более важно то, что конструкция цикла является второстепенной частью времени выполнения любого алгоритма, и вы должны сначала убедиться, что вы оптимизировали алгоритм и все остальное, что с ним связано. Оптимизация вашей конструкции цикла должна быть в конце списка приоритетов.
источник