Является ли "for(;;)" быстрее, чем "while (TRUE)"? Если нет, то почему люди используют его?
for (;;) {
//Something to be done repeatedly
}
Я видел, что такого рода вещи используются много, но я думаю, что это довольно странно...
Не было бы намного яснее сказать while(true)
, или что-то в этом роде?
Я предполагаю, что (как и причина, по которой многие программисты прибегают к загадочному коду) это крошечный запас быстрее?
почему, и это действительно стоит? Если да, то почему бы просто не определить его следующим образом:
#define while(true) for(;;)
Читайте также: что быстрее: пока(1) или в то время как(2)?
20 ответов:
- Это не быстрее.
- Если вы действительно заботитесь, скомпилировать с ассемблером вывода для вашей платформы и посмотреть, чтобы увидеть.
- Это не важно. Это не важно. Напишите свои бесконечные циклы, как вам нравится.
предпочитаю
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 */ }
нет никакой разницы в терминах машинного кода, который генерируется.
однако, просто чтобы противостоять тенденции, я бы сказал, что форма while(TRUE) гораздо более удобочитаема и интуитивно понятна, чем для (;;), и что читаемость и ясность являются гораздо более важными причинами для руководящих принципов кодирования, чем любые причины, которые я слышал для подхода for (;;) (я предпочитаю основывать свои руководящие принципы кодирования на твердых рассуждениях и/или доказательстве эффективности).
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);