2010-02-18 18 views
20

Lors de l'implémentation d'une boucle infinie, y a-t-il une différence dans l'utilisation de while(1) par rapport à for(;;) par rapport à goto?Lors de l'implémentation d'une boucle infinie, existe-t-il une différence dans l'utilisation de while (1) vs (;;) vs goto (in C)?

Merci, Chenz

+1

J'utilise toujours while. Je ne vois aucun point dans une boucle for construite de cette manière. C'est juste une préférence personnelle. (Il me semble qu'il manque des informations, alors que la boucle while me semble plus esthétique) – Tim

+0

techniquement, le 1 dans le temps est une condition qui devrait être testée à chaque itération. Je crois que tous les compilateurs communs sont assez intelligents pour faire un saut de celui-là plutôt que conditionnel. En dehors de cela, ils sont tous équivalents sauf pour le style. – falstro

+3

Quelle boucle infinie est plus rapide que l'autre? – Anonym

Répondre

44

Ils sont équivalents, même si vous éteignez l'optimiseur.

Exemple:

#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 avec gcc -O0 donne assemblage équivalent pour les 3 fonctions:

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 pour le code ARM :-) –

+0

Quelle commande a été utilisée pour produire cette sortie d'assemblage spécifique à partir du fichier objet? – bzeaman

0

D'après ce que je me souviens de mes « désassemblage ans », il ne fera pas beaucoup une différence (compilateurs sont assez intelligents ). Il s'agit plus d'esthétique IMO.

2

En C, true est mis en œuvre comme suit (selon le compilateur)

#define TRUE 1 

ou

#define TRUE (-1) 

ET false est mis en œuvre comme

#define FALSE 0 

si while (1) est équivalent à while (true) puisque 0 est considéré comme faux.

le while (1) == for (; ;) car il n'y a pas de condition d'arrêt.

qui est traduit en assembleur comme

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

donc si le code assembleur ne dispose pas d'une instruction ret ou exit, il est considéré comme une boucle infinie.

6

Je viens par rapport à la sortie de l'assembleur unoptimized de gcc:

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

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

Marque assembleur sortie:

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

Comparer les fichiers assembleur:

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

Comme vous pouvez le voir, il n'y a pas de différence significative. Voici la sortie

# 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 

Bien que ce n'est pas une preuve technique qu'ils sont les mêmes, je dirais qu'il est dans 99,9% des cas.

3

Aucune. Utilisez ce qui vous est le plus lisible

4

Il n'y a pratiquement aucune différence dans l'assemblage généré.Il est plus d'une question stylistique:

Aller - juste ooogly: sauts vers l'arrière, pas de bloc infini explicite

while (1) - mieux, exige la condition « factice » bien et vous serez souvent averti par le compilateur (niveau d'avertissement 4) ou outil d'analyse statique

pour (;;) peut ne pas être le plus joli, mais imho correspond le mieux parce que cette construction ne peut avoir aucune autre signification (par rapport à while). Mais d'autres personnes préfèrent (1) pour la "même" raison ...

2

Bien qu'il n'y ait pas de différence significative comme mentionné dans les autres articles, une raison courante d'utiliser for (;;) au lieu de while (1) est que les outils d'analyse statique (et certains compilateurs avec certains niveaux d'avertissement) se plaignent souvent de la boucle while.

Goto est un peu méchant, mais devrait produire le même code que les autres. Personnellement, je m'en tiens à for (;;) (pour garder Lint heureux), mais je n'ai aucun problème avec while (1).

3

while(1) et for(;;) sont exactement équivalents et les deux sont des idiomes bien compris pour coder des boucles infinies.

Je voudrais éviter l'utilisation de goto: pour rompre avec une boucle infinie ou passer à l'itération suivante, utilisez break et continue.