158 votes

tandis que (1) Vs. pour (;;) Y a-t-il une différence de vitesse?

Version longue...

Un collègue a affirmé aujourd'hui, après avoir vu mon utilisation d' while (1) dans un script Perl qui for (;;) est plus rapide. J'ai fait valoir qu'ils devraient être la même en espérant que l'interprète d'optimiser toutes les différences. J'ai créé un script qui sera exécuté pour 1 000 000 000 d'itérations de boucle et le même nombre de boucles while et d'enregistrer le temps entre les deux. J'ai pu trouver aucune différence notable. Mon collègue a dit qu'un professeur lui avait dit que l' while (1) était en train de faire une comparaison 1 == 1 et de la for (;;) ne l'était pas. Nous avons répété le même test avec l'100 fois le nombre d'itérations avec le C++, et la différence était minime. C'est toutefois un exemple graphique de façon beaucoup plus rapide code compilé peut être par rapport à un langage de script.

Version courte...

Est-il une raison de préférer un while (1) sur un for (;;) si vous avez besoin d'une boucle infinie de sortir de la?

Remarque: Si il n'est pas clair à partir de la question. C'était purement un plaisir de débat académique entre un couple d'amis. Je suis conscient que ce n'est pas un super concept important que tous les programmeurs doivent agoniser sur. Merci pour tous les beaux réponses que j'ai (et je suis sûr que d'autres) ont appris quelques choses de cette discussion.

Mise à jour: susmentionnés co-travailleur pesé dans une réponse ci-dessous.

Cité ici dans le cas où il obtient enterré.

Il est venu à partir d'un AMD assemblée programmeur. Il a déclaré que les programmeurs C (le peuple) ne se rendent pas compte que leur code a inefficiences. Il a dit aujourd'hui, même si, de compilateurs gcc sont très bonnes, et de mettre des gens comme lui de l'entreprise. Il a dit par exemple, et m'a dit à propos de l' while 1vs for(;;). Je l'utilise maintenant de sortir de l'habitude, mais gcc et surtout les interprètes va faire la même opération (un processeur de saut) pour ces deux jours, depuis qu'ils sont optimisés.

220voto

bdonlan Points 90068

En perl, ils donnent les mêmes opcodes:

 $ perl -MO=Concise -e 'for(;;) { print "foo\n" }'
a  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 2 -e:1) v ->3
9     <2> leaveloop vK/2 ->a
3        <{> enterloop(next->8 last->9 redo->4) v ->4
-        <@> lineseq vK ->9
4           <;> nextstate(main 1 -e:1) v ->5
7           <@> print vK ->8
5              <0> pushmark s ->6
6              <$> const[PV "foo\n"] s ->7
8           <0> unstack v ->4
-e syntax OK

$ perl -MO=Concise -e 'while(1) { print "foo\n" }'
a  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 2 -e:1) v ->3
9     <2> leaveloop vK/2 ->a
3        <{> enterloop(next->8 last->9 redo->4) v ->4
-        <@> lineseq vK ->9
4           <;> nextstate(main 1 -e:1) v ->5
7           <@> print vK ->8
5              <0> pushmark s ->6
6              <$> const[PV "foo\n"] s ->7
8           <0> unstack v ->4
-e syntax OK
 

De même dans GCC:

 #include <stdio.h>

void t_while() {
    while(1)
    	printf("foo\n");
}

void t_for() {
    for(;;)
    	printf("foo\n");
}

    .file   "test.c"
    .section    .rodata
.LC0:
    .string "foo"
    .text
.globl t_while
    .type   t_while, @function
t_while:
.LFB2:
    pushq   %rbp
.LCFI0:
    movq    %rsp, %rbp
.LCFI1:
.L2:
    movl    $.LC0, %edi
    call    puts
    jmp .L2
.LFE2:
    .size   t_while, .-t_while
.globl t_for
    .type   t_for, @function
t_for:
.LFB3:
    pushq   %rbp
.LCFI2:
    movq    %rsp, %rbp
.LCFI3:
.L5:
    movl    $.LC0, %edi
    call    puts
    jmp .L5
.LFE3:
    .size   t_for, .-t_for
    .section    .eh_frame,"a",@progbits
.Lframe1:
    .long   .LECIE1-.LSCIE1
.LSCIE1:
    .long   0x0
    .byte   0x1
    .string "zR"
    .uleb128 0x1
    .sleb128 -8
    .byte   0x10
    .uleb128 0x1
    .byte   0x3
    .byte   0xc
    .uleb128 0x7
    .uleb128 0x8
    .byte   0x90
    .uleb128 0x1
    .align 8
.LECIE1:
.LSFDE1:
    .long   .LEFDE1-.LASFDE1
.LASFDE1:
    .long   .LASFDE1-.Lframe1
    .long   .LFB2
    .long   .LFE2-.LFB2
    .uleb128 0x0
    .byte   0x4
    .long   .LCFI0-.LFB2
    .byte   0xe
    .uleb128 0x10
    .byte   0x86
    .uleb128 0x2
    .byte   0x4
    .long   .LCFI1-.LCFI0
    .byte   0xd
    .uleb128 0x6
    .align 8
.LEFDE1:
.LSFDE3:
    .long   .LEFDE3-.LASFDE3
.LASFDE3:
    .long   .LASFDE3-.Lframe1
    .long   .LFB3
    .long   .LFE3-.LFB3
    .uleb128 0x0
    .byte   0x4
    .long   .LCFI2-.LFB3
    .byte   0xe
    .uleb128 0x10
    .byte   0x86
    .uleb128 0x2
    .byte   0x4
    .long   .LCFI3-.LCFI2
    .byte   0xd
    .uleb128 0x6
    .align 8
.LEFDE3:
    .ident  "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
    .section    .note.GNU-stack,"",@progbits
 

Je suppose donc que la réponse est la même dans de nombreux compilateurs. Bien sûr, pour certains autres compilateurs, ce n'est pas forcément le cas, mais le code à l'intérieur de la boucle risque d'être plusieurs milliers de fois plus cher que la boucle elle-même, alors on s'en fout.

55voto

Martin Cote Points 12762

En utilisant GCC, ils semblent tous deux compiler dans le même langage d'assemblage:

 L2:
        jmp     L2
 

55voto

Bill the Lizard Points 147311

Il n'y a pas beaucoup de raisons de préférer l'un à l'autre. Je pense que while(1) et particulièrement while(true) sont plus lisibles que for(;;) , mais c'est juste ma préférence.

32voto

Richard Corden Points 12292

Il n'y a pas de différence selon le standard. 6.5.3/1 a:

La déclaration d'

for ( for-init-statement conditionopt ; expressionopt ) statement

est équivalent à

{
  for-init-statement
  while ( condition ) {
    statement
    expression ;
  }
}

Et 6.5.3/2 a:

L'une ou les deux de la condition et de l'expression peut être omis. Manque une condition implicite alors que la clause équivalente à while(true).

Ainsi, selon la norme C++ le code:

for (;;);

est exactement la même chose que:

{
  while (true) {
    ;
    ;
  }
}

28voto

sean e Points 6857

Le compilateur Visual C ++ utilisé pour émettre un avertissement pour

 while (1) 
 

(expression constante) mais pas pour

 for (;;)
 

J'ai continué à préférer for (;;) pour cette raison, mais je ne sais pas si le compilateur le fait encore ces jours-ci.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X