2010-02-18 8 views
20

Quando si implementa un ciclo infinito, c'è una differenza nell'uso di while(1) rispetto a for(;;) rispetto a goto?Quando si implementa un ciclo infinito, c'è una differenza nell'uso mentre (1) vs per (;;) vs goto (in C)?

Grazie, chenz

+1

Io uso sempre mentre. Non vedo alcun punto in un ciclo for costruito in tal modo. Questa è solo una preferenza personale. (Mi sembra che manchi informazioni, mentre il ciclo while sembra (per me) esteticamente più piacevole) – Tim

+0

tecnicamente, l'1 nel frattempo è una condizione che dovrebbe essere testata ad ogni iterazione. Credo che tutti i compilatori comuni siano abbastanza intelligenti da fare un salto fuori da quello, piuttosto che da uno condizionale. A parte questo, sono tutti equivalenti tranne che per lo stile. – falstro

+3

Quale loop infinito è più veloce dell'altro? – Anonym

risposta

44

Sono equivalenti, anche se si disattiva l'ottimizzatore.

Esempio:

#include <stdio.h> 

extern void f(void) { 
    while(1) { 
     putchar(' '); 
    } 
} 

extern void g(void) { 
    for(;;){ 
     putchar(' '); 
    } 
} 

extern void h(void) { 
    z: 
     putchar(' '); 
    goto z; 
} 

compilazione con gcc -O0 dà montaggio equivalente per tutti e 3 funzioni:

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 
+8

+1 per codice ARM :-) –

+0

Quale comando è stato utilizzato per produrre questo output di assembly specifico dal file oggetto? – bzeaman

0

Da quello che mi ricordo dei miei "anni di smontaggio", ma non farà molta differenza (compilatori sono intelligenti abbastanza). È più sull'estetica IMO.

2

In C, true è implementato (seconda compilatore)

#define TRUE 1 

o

#define TRUE (-1) 

E falso è implementato come

#define FALSE 0 

come segue in modo while (1) è equivalente a while (true) poiché 0 è considerato falso.

il while (1) == for (; ;) in quanto non ci sono condizioni di arresto.

che viene tradotto a dell'assemblatore

:loop 
    ... 
    ... 
    ... 
    goto loop 

quindi se il codice assemblatore non ha un'istruzione ret o exit, è considerato un ciclo infinito.

6

Ho confrontato l'uscita assemblatore non ottimizzata di gcc:

# cat while.c 
int main() { 
    while(1) {}; 
    return 0; 
} 

# cat forloop.c 
int main() { 
    for (;;) { }; 
    return 0; 
} 

Fare assemblatore uscita:

# gcc -S while.c 
# gcc -S forloop.c 

confrontare i file assembler:

# diff forloop.s while.s 
1c1 
< .file "forloop.c" 
--- 
> .file "while.c" 

Come potete vedere ci sono differenze significative. Ecco l'output

# 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 

Mentre questa non è una prova tecnica che sono la stessa cosa, direi che è nel 99,9% dei casi.

3

Nessuno. Utilizzare ciò che è più leggibile per voi

4

Non c'è praticamente alcuna differenza nell'assemblaggio generato.E 'più di un problema stilistico:

Goto - basta ooogly: salti all'indietro, nessun blocco infinito esplicito

while (1) - meglio, richiede "fittizio" condizione però e sarete spesso avvertito da compilatore (livello di avviso 4) o strumento di analisi statica

for (;;) potrebbe non essere la più bella, ma imho si adatta meglio perché questo costrutto non può avere altro significato (rispetto a while). Ma alcune altre persone preferiscono (1) per la "stessa" ragione ...

2

Sebbene non ci siano differenze significative come menzionato negli altri post, un motivo comune per usare for (;;) invece di while (1) è che gli strumenti di analisi statica (e alcuni compilatori con determinati livelli di avviso) si lamentano spesso del ciclo while.

Goto è un po 'sgradevole, ma dovrebbe produrre lo stesso codice degli altri. Personalmente, mi attengo a for (;;) (per mantenere Lint felice), ma non ho problemi con while (1).

3

while(1) e for(;;) sono esattamente equivalenti ed entrambi sono idiomi ben compresi per codificare cicli infiniti.

avrei evitare l'uso di goto: rompere da un ciclo infinito o di procedere alla prossima iterazione, utilizzare break e continue.