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
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
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
+1 per codice ARM :-) –
Quale comando è stato utilizzato per produrre questo output di assembly specifico dal file oggetto? – bzeaman
Da quello che mi ricordo dei miei "anni di smontaggio", ma non farà molta differenza (compilatori sono intelligenti abbastanza). È più sull'estetica IMO.
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.
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.
Nessuno. Utilizzare ciò che è più leggibile per voi
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 ...
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)
.
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
.
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
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
Quale loop infinito è più veloce dell'altro? – Anonym