При реализации бесконечного цикла есть ли разница в использовании while(1)
vs for(;;)
vs goto
?
Спасибо, Ченз
При реализации бесконечного цикла есть ли разница в использовании while(1)
vs for(;;)
vs goto
?
Спасибо, Ченз
Они эквивалентны, даже если вы выключите оптимизатор.
Пример:
#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
дает эквивалентную сборку для всех 3 функций:
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% случаев.
В сгенерированной сборке практически нет разницы. Это скорее стилистический вопрос:
Goto - просто ooogly: прыжок назад, без явного бесконечного блока
while (1) - лучше, требует "фиктивного" условия, и вы часто будете предупреждены компилятором (уровень предупреждения 4) или инструментом статического анализа.
for (;;) может быть не самым красивым, но imho подходит лучше всего, потому что эта конструкция не может иметь никакого другого значения (по сравнению с while). Но некоторые другие люди предпочитают while (1) по "той же" причине ...
Хотя нет существенной разницы, как упоминалось в других сообщениях, распространенной причиной использования for (;;)
вместо while (1)
является то, что инструменты статического анализа (и некоторые компиляторы с определенными уровнями предупреждений) часто жалуются на цикл while.
Goto немного неприятен, но должен выдавать тот же код, что и другие. Лично я придерживаюсь for (;;)
(чтобы Линт был доволен), но у меня нет проблем с while (1)
.
while(1)
и for(;;)
в точности эквивалентны, и обе являются хорошо понятными идиомами для кодирования бесконечных циклов.
Я бы избегал использования goto
: чтобы выйти из бесконечного цикла или перейти к следующей итерации, используйте break
и continue
.
Никто. Используйте то, что вам удобнее всего
В C true
реализован следующим образом (в зависимости от компилятора)
#define TRUE 1
or
#define TRUE (-1)
И ложь реализована как
#define FALSE 0
поэтому while (1)
эквивалентно while (true)
, поскольку 0 считается ложным.
while (1) == for (; ;)
, поскольку нет условий остановки.
который переводится на ассемблер как
:loop
...
...
...
goto loop
поэтому, если в коде ассемблера нет инструкций ret
или exit
, это считается бесконечным циклом.
Судя по тому, что я вспоминал о "годах дизассемблирования", это не будет иметь большого значения (компиляторы достаточно умны). Это больше об эстетике ИМО.
for(;;)
позволяет вам#define ever (;;)
и использоватьfor ever {...
;) - person kennytm   schedule 18.02.2010while()
иfor()
в целом. Этот вопрос касается бесконечных циклов. - person tomlogic   schedule 19.02.2010#define indefinitely for(;;)
indefinitely {}
- person Andrew   schedule 27.05.2021