При реализации бесконечного цикла существует ли разница в использовании while(1)
vs for(;;)
vs goto
?
Спасибо, Chenz
При реализации бесконечного цикла существует ли разница в использовании while(1)
vs for(;;)
vs goto
?
Спасибо, Chenz
Они эквивалентны, даже если вы отключили оптимизатор.
Пример:
#include <stdio.h>
extern void f(void) {
while(1) {
putchar(' ');
}
}
extern void g(void) {
for(;;){
putchar(' ');
}
}
extern void h(void) {
z:
putchar(' ');
goto z;
}
Компиляция с помощью gcc -O0
дает эквивалентную сборку для всех трех функций:
f:
; [ EXTERNAL ]
;
+00000 00000fb4 80402DE9 stmdb sp!,{r7,lr}
+00004 00000fb8 00708DE2 add r7,sp,#0x0
+00008 00000fbc 2000A0E3 loc_000008: mov r0,#0x20
+0000c 00000fc0 0A0000EB bl putchar (stub)
+00010 00000fc4 FCFFFFEA b loc_000008
;
;
g:
; [ EXTERNAL ]
;
+00000 00000fc8 80402DE9 stmdb sp!,{r7,lr}
+00004 00000fcc 00708DE2 add r7,sp,#0x0
+00008 00000fd0 2000A0E3 loc_000008: mov r0,#0x20
+0000c 00000fd4 050000EB bl putchar (stub)
+00010 00000fd8 FCFFFFEA b loc_000008
;
;
h:
; [ EXTERNAL ]
;
+00000 00000fdc 80402DE9 stmdb sp!,{r7,lr}
+00004 00000fe0 00708DE2 add r7,sp,#0x0
+00008 00000fe4 2000A0E3 loc_000008: mov r0,#0x20
+0000c 00000fe8 000000EB bl putchar (stub)
+00010 00000fec FCFFFFEA b loc_000008
Я просто сравнил неоптимизированный вывод ассемблера gcc:
# cat while.c
int main() {
while(1) {};
return 0;
}
# cat forloop.c
int main() {
for (;;) { };
return 0;
}
Сделайте вывод ассемблера:
# gcc -S while.c
# gcc -S forloop.c
Сравните файлы ассемблера:
# diff forloop.s while.s
1c1
< .file "forloop.c"
---
> .file "while.c"
Как вы видите, существенных различий нет. Вот вывод
# cat while.s
.file "while.c"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
.L2:
jmp .L2 # this is the loop in both cases
.size main, .-main
.ident "GCC: (GNU) 4.4.3"
.section .note.GNU-stack,"",@progbits
Хотя это не техническое доказательство того, что они одинаковы, я бы сказал, что это в 99,9% случаев.
В сгенерированной сборке вряд ли есть какая-либо разница. Это скорее стилистическая проблема:
Перейти в - просто ооо: прыгает назад, без явного бесконечного блока
while (1) - лучше, требуется условие "dummy", хотя вы будете часто предупреждаться компилятором (уровень предупреждения 4) или инструментом статического анализа
for (;;) может быть не самым красивым, но imho лучше всего подходит, потому что эта конструкция не может иметь никакого другого значения (по сравнению с тем временем). Но некоторые другие люди предпочитают пока (1) по "той же" причине...
Отсутствует. Используйте то, что наиболее читаемо для вас
while(1)
и for(;;)
являются в точности эквивалентными, и оба являются хорошо понятыми идиомами для кодирования бесконечных циклов.
Я бы избегал использования goto
: чтобы выйти из бесконечного цикла или перейти к следующей итерации, используйте break
и continue
.
В C, true
реализуется следующим образом (в зависимости от компилятора)
#define TRUE 1
или
#define TRUE (-1)
И false выполняется как
#define FALSE 0
поэтому while (1)
эквивалентно while (true)
, поскольку 0 считается ложным.
the while (1) == for (; ;)
, так как условия остановки отсутствуют.
который переводится на ассемблер как
:loop
...
...
...
goto loop
поэтому, если код ассемблера не имеет инструкции ret
или exit
, он считается бесконечным циклом.
Несмотря на отсутствие существенных различий, как упоминалось в других сообщениях, общая причина использования for (;;)
вместо while (1)
заключается в том, что инструменты статического анализа (и некоторые компиляторы с определенными уровнями предупреждений) часто жалуются на цикл while.
Goto немного противно, но должен содержать тот же код, что и другие. Лично я придерживаюсь for (;;)
(чтобы сохранить Lint happy), но у меня нет проблем с while (1)
.
Из того, что я вспоминаю о "разборке лет", это не будет иметь большого значения (компиляторы достаточно умны). Это больше об эстетике ИМО.