Подтвердить что ты не робот

При реализации бесконечного цикла существует ли разница в использовании while (1) vs for (;;) vs goto (в C)?

При реализации бесконечного цикла существует ли разница в использовании while(1) vs for(;;) vs goto?

Спасибо, Chenz

4b9b3361

Ответ 1

Они эквивалентны, даже если вы отключили оптимизатор.

Пример:

#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

Ответ 2

Я просто сравнил неоптимизированный вывод ассемблера 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% случаев.

Ответ 3

В сгенерированной сборке вряд ли есть какая-либо разница. Это скорее стилистическая проблема:

Перейти в - просто ооо: прыгает назад, без явного бесконечного блока

while (1) - лучше, требуется условие "dummy", хотя вы будете часто предупреждаться компилятором (уровень предупреждения 4) или инструментом статического анализа

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

Ответ 4

Отсутствует. Используйте то, что наиболее читаемо для вас

Ответ 5

while(1) и for(;;) являются в точности эквивалентными, и оба являются хорошо понятыми идиомами для кодирования бесконечных циклов.

Я бы избегал использования goto: чтобы выйти из бесконечного цикла или перейти к следующей итерации, используйте break и continue.

Ответ 6

В 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, он считается бесконечным циклом.

Ответ 7

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

Goto немного противно, но должен содержать тот же код, что и другие. Лично я придерживаюсь for (;;) (чтобы сохранить Lint happy), но у меня нет проблем с while (1).

Ответ 8

Из того, что я вспоминаю о "разборке лет", это не будет иметь большого значения (компиляторы достаточно умны). Это больше об эстетике ИМО.