2010-02-18 4 views
20

Gibt es bei der Implementierung einer Endlosschleife einen Unterschied zwischen while(1) vs for(;;) vs goto?Gibt es bei der Implementierung einer Endlosschleife einen Unterschied bei der Verwendung von while (1) vs für (;;) vs goto (in C)?

Danke, Chenz

+1

Ich benutze immer während. Ich sehe keinen Sinn in einer so konstruierten for-Schleife. Das ist nur eine persönliche Vorliebe. (Es scheint mir zu fehlen Informationen, während die While-Schleife (für mich) ästhetisch ansprechend aussieht) – Tim

+0

technisch ist die 1 in der Zeit eine Bedingung, die bei jeder Iteration getestet werden sollte. Ich glaube, dass alle gängigen Compiler schlau genug sind, um aus diesem einen Sprung zu machen, anstatt einen bedingten. Abgesehen davon sind sie alle gleich, außer für Stil. – falstro

+3

Welche Endlosschleife ist schneller als die andere? – Anonym

Antwort

44

Sie sind äquivalent, auch wenn Sie den Optimierer ausschalten.

Beispiel:

#include <stdio.h> 

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

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

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

Compile mit gcc -O0 gibt gleichwertige Montag für alle drei Funktionen:

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 für ARM-Code :-) –

+0

Welcher Befehl wurde verwendet, um diese spezifische Assembly-Ausgabe aus der Objektdatei zu erzeugen? – bzeaman

0

Von dem, was ich von meinen „Auseinanderbauen Jahren“ erinnern, es nicht viel Unterschied machen wird (Compiler sind Smart genug). Es geht mehr um Ästhetik IMO.

2

In C wird true implementiert, wie folgt (in Abhängigkeit von Compiler)

#define TRUE 1 

oder

#define TRUE (-1) 

UND falsch ist implementiert als

#define FALSE 0 

so while (1) entspricht while (true) seit 0 gilt als falsch.

die , da es keine Haltebedingung gibt.

die als

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

so, wenn der Assembler-Code ein ret oder exit Anweisung muss nicht Assembler übersetzt wird, wird es eine unendliche Schleife betrachtet.

6

ich im Vergleich nur die nicht optimierte Assembler Ausgabe von gcc:

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

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

Assembler Stellen Ausgabe:

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

Vergleichen Assembler-Dateien:

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

Wie Sie gibt es keine signifikanten Unterschiede zu sehen. Hier die Ausgabe ist

# 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 

Zwar ist dies kein technischer Beweis dafür, dass sie gleich sind, würde ich sagen, dass es in 99,9% der Fälle ist.

3

Keine. Verwenden Sie, was am besten lesbar ist

4

Es gibt kaum einen Unterschied in der generierten Baugruppe.Es ist eher eine stilistische Frage:

Goto - nur ooogly: springt rückwärts, keinen expliziten unendlichen Block

while (1) - besser, erfordert "Dummy" Zustand obwohl, und Sie werden oft sein Warnung durch Compiler (Warnstufe 4) oder statisches Analysewerkzeug

für (;;) ist vielleicht nicht die schönste, aber imho passt am besten, weil dieses Konstrukt keine andere Bedeutung haben kann (im Vergleich zu while). Aber einige andere Leute bevorzugen, während (1) aus dem gleichen "Grund" ...

2

Obwohl es keinen signifikanten Unterschied gibt, wie in den anderen Posts erwähnt, ist ein häufiger Grund, for (;;) anstelle von while (1) zu verwenden, dass statische Analysetools (und einige Compiler mit bestimmten Warnstufen) beschweren sich häufig über die while-Schleife.

Goto ist ein bisschen böse, sollte aber den gleichen Code wie die anderen produzieren. Persönlich bleibe ich bei for (;;) (um Lint glücklich zu halten), aber ich habe kein Problem mit while (1).

3

while(1) und for(;;) sind genau äquivalent und beide sind gut verstandene Idiome Endlosschleifen zu codieren.

würde ich die Verwendung von goto vermeiden: von einer Endlos-Schleife zu brechen oder zu der nächsten Iteration zu gehen, verwenden break und continue.