web-dev-qa-db-fra.com

"For (;;)" est-il plus rapide que "while (TRUE)"? Sinon, pourquoi les gens l'utilisent-ils?

for (;;) {
    //Something to be done repeatedly
}

J'ai vu ce genre de chose beaucoup utilisé, mais je pense que c'est plutôt étrange ... Ne serait-il pas beaucoup plus clair de dire while(true), ou quelque chose du genre?

Je suppose que (comme c'est la raison pour laquelle beaucoup de programmeurs ont recours à du code cryptique), c'est une toute petite marge plus rapide?

Pourquoi, et est-ce vraiment la peine? Si oui, pourquoi ne pas simplement le définir de cette façon:

#define while(true) for(;;)

Voir aussi: Quel est le plus rapide: while (1) ou while (2)?

158
Chris Cooper
  1. Ce n'est pas plus rapide.
  2. Si vous vous souciez vraiment, compilez avec la sortie de l'assembleur pour votre plate-forme et regardez pour voir.
  3. Ça n'a pas d'importance. Cela n'a jamais d'importance. Écrivez vos boucles infinies comme vous le souhaitez.
255
Ben Zotto

Je préfère for(;;) pour deux raisons.

La première est que certains compilateurs produisent des avertissements sur while(true) (quelque chose comme "la condition de boucle est constante"). Éviter les avertissements est toujours une bonne chose à faire.

Un autre est que je pense que for(;;) est plus clair et plus révélateur. Je veux une boucle infinie. Il n'a littéralement a aucune condition, cela ne dépend de rien. Je veux juste que ça continue pour toujours, jusqu'à ce que je fasse quelque chose pour en sortir.

Alors qu'avec while(true), eh bien, qu'est-ce qui a vraiment à voir avec quoi que ce soit? Je ne suis pas intéressé à boucler jusqu'à ce que true devienne faux, c'est ce que cette forme dit littéralement (boucle alors que true est vrai). Je veux juste faire une boucle.

Et non, il n'y a absolument aucune différence de performances.

169
jalf

Personnellement, j'utilise for (;;) car il n'y a pas de chiffres, c'est juste un mot-clé. Je le préfère à while (true), while (1), while (42), while (!0) etc etc.

56
ta.speot.is

À cause de Dennis Ritchie

  • J'ai commencé à utiliser for (;;) parce que c'est ainsi que Dennis Ritchie le fait dans K&R, et lorsque j'apprends une nouvelle langue, j'essaie toujours d'imiter les gars intelligents.

  • C'est du C/C++ idiomatique. Il est probablement préférable à long terme de s'y habituer si vous prévoyez d'en faire beaucoup dans l'espace C/C++.

  • Votre #define ne fonctionnera pas, car la chose en cours de définition doit ressembler à un identifiant C.

  • Tous les compilateurs modernes généreront le même code pour les deux constructions.

49
Mark Harrison

Ce n'est certainement pas plus rapide dans aucun compilateur sensé. Ils seront tous deux compilés en sauts inconditionnels. La version for est plus facile à taper (comme l'a dit Neil) et sera claire si vous comprenez la syntaxe de boucle.

Si vous êtes curieux, voici ce que gcc 4.4.1 me donne pour x86. Les deux utilisent l'instruction x86 JMP .

void while_infinite()
{
    while(1)
    {
    puts("while");
    }
}

void for_infinite()
{
    for(;;)
    {
    puts("for");
    }
}

compile (en partie):

.LC0:
.string "while"
.text
.globl while_infinite
    .type   while_infinite, @function
while_infinite:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $24, %esp
.L2:
    movl    $.LC0, (%esp)
    call    puts
    jmp .L2
    .size   while_infinite, .-while_infinite
    .section    .rodata
.LC1:
    .string "for"
    .text
.globl for_infinite
    .type   for_infinite, @function
for_infinite:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $24, %esp
.L5:
    movl    $.LC1, (%esp)
    call    puts
    jmp .L5
    .size   for_infinite, .-for_infinite
46
Matthew Flaschen

Je préfère for (;;) car c'est le plus cohérent dans différents langages de type C.

En C++ while (true) est très bien, mais en C vous dépendez d'un en-tête pour définir true, mais TRUE est aussi une macro couramment utilisée. Si vous utilisez while (1) c'est correct en C et C++ et JavaScript, mais pas Java ou C #, qui nécessitent que la condition de boucle soit booléenne, comme while (true) ou while (1 == 1). En PHP, les mots-clés sont insensibles à la casse mais le langage préfère la majuscule TRUE.

Cependant, for (;;) est toujours complètement correct dans toutes ces langues.

41
Boann

Personnellement, je préfère l'idiome for (;;) (qui sera compilé dans le même code que while (TRUE).

L'utilisation de while (TRUE) peut être plus lisible dans un sens, j'ai décidé d'utiliser l'idiome for (;;) parce que il se démarque.

Une construction de boucle infinie devrait être facilement remarquée ou appelée dans le code, et je pense personnellement que le style for (;;) le fait un peu mieux que while (TRUE) ou while (1).

Je rappelle également que certains compilateurs émettent des avertissements lorsque l'expression de contrôle d'une boucle while est une constante. Je ne pense pas que cela arrive trop, mais juste le potentiel d'avertissements fallacieux me suffit pour vouloir l'éviter.

21
Michael Burr

J'ai vu que certaines personnes le préfèrent parce qu'elles ont un #define quelque part comme ceci:

#define EVER ;;

Ce qui leur permet d'écrire ceci:

for (EVER)
{
    /* blah */
}
17
rmeador

Qu'en est-il (si votre langue le prend en charge):

start:
/* BLAH */
goto start;
16
bungle

Il n'y a aucune différence en termes de code machine généré.

Cependant, pour inverser la tendance, je dirais que la forme while (TRUE) est beaucoup plus lisible et intuitive que pour (;;), et que la lisibilité et la clarté sont des raisons beaucoup plus importantes pour les directives de codage que toutes les raisons pour lesquelles je '' J'ai entendu parler de l'approche for (;;) (je préfère baser mes directives de codage sur un raisonnement solide et/ou une preuve d'efficacité moi-même).

12
Jason Williams

Pas seulement un modèle bien connu, mais un idiome standard en C (et C++)

11
James McLeod

Les deux doivent être identiques si votre code est optimisé par le compilateur. Pour expliquer ce que je veux dire par optimisation, voici un exemple de code écrit en MSVC 10:

int x = 0;

while(true) // for(;;)
{
    x +=1;

    printf("%d", x);
}

Si vous le construisez en mode Debug (sans aucune optimisation (/ Od)) le démontage montre la nette différence. Il y a des instructions supplémentaires pour la condition true dans while.

while(true)
00D313A5  mov         eax,1                //extra 
00D313AA  test        eax,eax              //extra
00D313AC  je          main+39h (0D313B9h)  //extra
    {
        x +=1;
00D313AE  mov         eax,dword ptr [x]  
00D313B1  add         eax,1  
00D313B4  mov         dword ptr [x],eax  
    printf("%d", x);
    ...
    }
00D313B7  jmp         main+25h (0D313A5h)  


for(;;)
    {
        x +=1;
00D213A5  mov         eax,dword ptr [x]  
00D213A8  add         eax,1  
00D213AB  mov         dword ptr [x],eax  
    printf("%d", x);
    ...
    }
00D213AE  jmp         main+25h (0D213A5h)  

Cependant, si vous construisez votre code en mode Release (avec par défaut Maximize Speed ​​(/ O2)) vous obtenez la même sortie pour les deux. Les deux boucles sont réduites à une instruction de saut.

for(;;)
    {
        x +=1;
01291010  inc         esi  

        printf("%d", x);
    ...
    }
0129101C  jmp         main+10h (1291010h)  

    while(true)
    {
        x +=1;
00311010  inc         esi  

        printf("%d", x);
    ...
    }
0031101C  jmp         main+10h (311010h)  

Celui que vous utiliserez n'a pas d'importance pour un compilateur décent avec optimisation de la vitesse activée.

11
SylvanBlack
while(true)

génère un avertissement avec Visual Studio (la condition est constante). La plupart des endroits où j'ai travaillé compilent des builds de production avec des avertissements en tant qu'erreurs. Alors

for(;;)

est préféré.

11
Michael

C'est une question de préférence personnelle qui est plus rapide. Personnellement, je suis un touchtypist et ne regarde jamais mon clavier pendant la programmation - je peux taper les 104 touches de mon clavier.

Je trouve si plus rapide de taper "while (TRUE)".

J'ai mentalement ajouté quelques mesures de mouvement des doigts et les ai totalisées. "for (;;)" a environ 12 largeurs de touches de mouvements vers l'arrière et la quatrième (entre les touches home et les touches, et entre les touches home et la touche MAJ) "tandis que (TRUE)" a environ 14 largeurs de clés de mouvements vers l'arrière et Quatrième.

Cependant, je suis beaucoup moins sujet aux erreurs lorsque je tape ce dernier. Je pense mentalement avec des mots à la fois, donc je trouve plus rapide de taper des choses comme "nIndex" que des acronymes tels que "nIdx" car je dois épeler mentalement le lettrage plutôt que de le dire dans mon esprit et laisser mes doigts s'auto -tapez le mot (comme faire du vélo)

(Mon benchmark TypingTest.com = 136 WPM)

9
Mark Rejhon

Toutes les bonnes réponses - le comportement doit être exactement le même.

CEPENDANT - Supposons simplement que cela DID fait une différence. Supposons que l'un d'eux prenne 3 instructions supplémentaires par itération.

Devriez-vous vous en soucier?

UNIQUEMENT si ce que vous faites à l'intérieur de la boucle est presque rien, ce qui est presque jamais le cas.

Mon point est qu'il y a une micro-optimisation et une macro-optimisation. La micro-optimisation, c'est comme "se faire couper les cheveux pour perdre du poids".

6
Mike Dunlavey

Je ne peux pas imaginer qu'un compilateur utile génère un code différent. Même si c'était le cas, il n'y aurait aucun moyen de déterminer sans tester le compilateur particulier qui était plus efficace.

Cependant, je vous suggère de préférer for(;;) pour les raisons suivantes:

  • un certain nombre de compilateurs que j'ai utilisés génèrent un avertissement d'expression constante pendant tout (vrai) avec les paramètres de niveau d'avertissement appropriés.

  • dans votre exemple, la macro TRUE peut ne pas être définie comme vous vous y attendez

  • il existe de nombreuses variantes possibles de la boucle while infinie telles que while(1), while(true), while(1==1) etc; donc for(;;) est susceptible d'entraîner une plus grande cohérence.

5
Clifford
for(;;Sleep(50))
{
    // Lots of code
}

Est plus clair que:

while(true)
{
    // Lots of code
    Sleep(50);
}

Cela ne s'applique pas si vous n'utilisez pas Sleep().

5
Armada

La boucle "forever" est populaire dans les systèmes embarqués comme boucle d'arrière-plan. Certaines personnes l'implémentent comme:

for (; ;)
{
 // Stuff done in background loop
}

Et parfois, il est implémenté comme:

while (TRUE /* or use 1 */)
{
 // Stuff done in background loop
}

Et encore une autre implémentation est:

do
{
 // Stuff done in background loop
} while (1 /* or TRUE */);

Un compilateur d'optimisation doit générer le code d'assemblage identique ou similaire pour ces fragments. Une remarque importante: le temps d'exécution des boucles n'est pas un gros problème car ces boucles durent indéfiniment et plus de temps est consacré à la section de traitement.

4
Thomas Matthews

Je suppose que tandis que (true) est plus lisible que pour (;;) - son aspect comme programmeur manque quelque chose dans la boucle for :)

et qui se soucie lequel est le plus rapide le cas échéant

2
nik

La raison la plus importante d'utiliser "for (;;)" est la peur d'utiliser "while (TRUE)" lorsque vous effectuez une programmation exploratoire. Il est plus facile de contrôler la quantité de répétitions avec "pour", et aussi, de convertir la boucle "pour" en infini.

Par exemple, si vous construisez une fonction récursive, vous pouvez limiter la quantité d'appels à la fonction avant de la convertir en boucle infinie.

    for(int i=0;i<1000;i++) recursiveFunction(oneParam);

Quand je suis sûr de ma fonction, je la convertis en boucle infinie:

    for(;;) recursiveFunction(oneParam);
2
Ignacio Cortorreal