É “for (;;)” mais rápido que “while (TRUE)”? Se não, por que as pessoas usam isso?

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

Eu vi esse tipo de coisa muito usada, mas eu acho que é um pouco estranho … Não seria muito mais claro dizer while(true) , ou algo assim?

Eu estou supondo que (como é a razão para muitos programadores recorrerem ao código enigmático) esta é uma pequena margem mais rápida?

Por que e vale mesmo a pena? Se sim, por que não defini-lo assim:

 #define while(true) for(;;) 

Veja também: Qual é mais rápido: while (1) ou while (2)?

  1. Não é mais rápido.
  2. Se você realmente se importa, compile com a saída do assembler para sua plataforma e procure ver.
  3. Não importa. Isso nunca importa. Escreva seus loops infinitos como quiser.

Eu prefiro for(;;) por duas razões.

Uma é que alguns compiladores produzem avisos em while(true) (algo como “condição de loop é constante”). Evitar avisos é sempre uma boa coisa a fazer.

Outra é que eu acho que for(;;) é mais claro e mais revelador. Eu quero um loop infinito. Literalmente não tem condição, depende de nada. Eu só quero que continue para sempre, até que eu faça algo para sair disso.

Considerando que com o while(true) , bem, o que é verdade tem a ver com alguma coisa? Eu não estou interessado em looping até que true se torne false, que é o que esta forma literalmente diz (loop enquanto true é true). Eu só quero fazer um loop.

E não, não há absolutamente nenhuma diferença de desempenho.

Pessoalmente eu uso for (;;) porque não há números nele, é apenas uma palavra-chave. Eu prefiro a while (true) , while (1) , while (42) , while (!0) etc etc.

Por causa de Dennis Ritchie

  • Eu comecei a usar for (;;) porque é assim que Dennis Ritchie faz isso em K & R, e ao aprender um novo idioma eu sempre tento imitar os espertos.

  • Isto é idiomático em C / C ++. É provavelmente melhor a longo prazo para se acostumar com isso, se você planeja fazer muito no espaço C / C ++.

  • Seu #define não funcionará, já que a coisa que está sendo # define tem que parecer com um identificador C.

  • Todos os compiladores modernos irão gerar o mesmo código para as duas construções.

Certamente não é mais rápido em qualquer compilador sensato. Ambos serão compilados em saltos incondicionais. A versão for é mais fácil de digitar (como disse Neil) e ficará clara se você entender a syntax do loop.

Se você está curioso, aqui está o que o gcc 4.4.1 me oferece para o x86. Ambos usam a instrução x86 JMP .

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

compila para (em parte):

 .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 

Eu prefiro for (;;) porque é o mais consistente em diferentes linguagens semelhantes a C.

Em C ++ while (true) é bom, mas em C você depende de um header para definir true , mas TRUE é uma macro comumente usada. Se você usar while (1) está correto em C e C ++, e JavaScript, mas não em Java ou C #, que requerem que a condição de loop seja um booleano, como while (true) ou while (1 == 1) . No PHP, as palavras-chave diferenciam maiúsculas de minúsculas, mas a linguagem prefere a palavra-chave TRUE .

No entanto, for (;;) é sempre completamente correto em todos esses idiomas.

Eu pessoalmente prefiro o for (;;) idiom (que irá compilar para o mesmo código que while (TRUE) .

Usando while (TRUE) pode ser mais legível em um sentido, eu decidi usar o idioma for (;;) porque ele se destaca .

Uma construção de loop infinito deve ser facilmente notada ou chamada no código, e eu pessoalmente acho que o estilo for (;;) faz isso um pouco melhor que while (TRUE) ou while (1) .

Além disso, lembro que alguns compiladores emitem avisos quando a expressão controladora de um loop while é uma constante. Eu não acho que isso aconteça demais, mas apenas o potencial para avisos espúrios é suficiente para eu querer evitá-lo.

Eu vi algumas pessoas preferirem porque eles têm um #define em algum lugar como este:

 #define EVER ;; 

Que lhes permite escrever isso:

 for (EVER) { /* blah */ } 

E se (se o seu idioma suportar isso):

 start: /* BLAH */ goto start; 
 while(true) 

gera um aviso com o Visual Studio (condição é constante). A maioria dos lugares em que trabalhei compilar a produção é construída com avisos como erros. assim

 for(;;) 

é preferível.

Não apenas um padrão conhecido, mas um idioma padrão em C (e C ++)

Não há diferença em termos do código de máquina gerado.

No entanto, apenas para resistir à tendência, eu diria que a forma while (TRUE) é muito mais legível e intuitiva do que para (;;), e que legibilidade e clareza são razões muito mais importantes para diretrizes de codificação do que qualquer outra razão. Já ouvi falar da abordagem (;;) (eu prefiro basear minhas diretrizes de codificação em raciocínio sólido e / ou prova de eficácia eu mesmo).

Ambos devem ser iguais se o seu código for otimizado pelo compilador. Para explicar o que quero dizer com otimização, aqui está um exemplo de código escrito no MSVC 10:

 int x = 0; while(true) // for(;;) { x +=1; printf("%d", x); } 

Se você construir no modo de debugging ( sem qualquer otimização (/ Od) ), a desassembly mostra a clara diferença. Há instruções extras para a true condição interna 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) 

No entanto, se você criar seu código no modo Release (com o padrão Maximize Speed ​​(/ O2) ), obterá a mesma saída para ambos. Ambos os loops são reduzidos a uma instrução de salto.

 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) 

Qualquer que seja o seu uso, não importa se um compilador decente com a otimização de velocidade está ativada.

É uma questão de preferência pessoal, o caminho é mais rápido. Pessoalmente, eu sou um touchtypist e nunca olho para o meu teclado, durante a programação – eu posso tocar todas as 104 teclas do teclado.

Acho mais rápido digitar “while (TRUE)”.

Eu mentalmente adicionei algumas medidas de movimento dos dedos e as somei. “for (;;)” tem cerca de 12 larguras de tecla de retrocesso e quarto (entre as teclas home e as teclas, e entre as teclas home e SHIFT) “while (TRUE)” tem cerca de 14 larguras de tecla de volta e quarto.

No entanto, sou muito menos propenso a erros ao digitar o último. Eu mentalmente penso em palavras de cada vez, então eu acho mais rápido escrever coisas como “nIndex” do que acrônimos como “nIdx” porque eu tenho que realmente mentalmente soletrar as letras ao invés de falar dentro da minha mente e deixar meus dedos auto tipo-a palavra (como andar de bicicleta)

(Meu benchmark TypingTest.com = 136 WPM)

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

É mais claro que:

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

Não que isso se aplique se você não estiver usando o Sleep() .

Todas as boas respostas – o comportamento deve ser exatamente o mesmo.

No entanto – apenas suponho que fez a diferença. Suponha que um deles tenha recebido mais 3 instruções por iteração.

Você deve se importar?

SOMENTE se o que você faz dentro do loop é quase nada , o que quase nunca é o caso.

Meu ponto é, há micro-otimização e otimização macro. Micro-otimização é como “cortar o cabelo para perder peso”.

Não consigo imaginar que um compilador que vale a pena possa gerar qualquer código diferente. Mesmo se o fizesse, não haveria como determinar sem testar o compilador específico que era mais eficiente.

No entanto, sugiro que você prefira for(;;) pelos seguintes motivos:

  • um número de compiladores que usei gerará um aviso de expressão constante para while (true) com configurações de nível de aviso apropriadas.

  • no seu exemplo, a macro TRUE pode não ser definida como você espera

  • há muitas variantes possíveis do loop while infinito, como while(1) , while(true) , while(1==1) etc .; então, for(;;) é provável que resulte em maior consistência.

O loop “para sempre” é popular em sistemas embarcados como um loop de fundo. Algumas pessoas implementam como:

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

E às vezes é implementado como:

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

E ainda outra implementação é:

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

Um compilador de otimização deve gerar o código de assembly igual ou semelhante para esses fragments. Uma nota importante: o tempo de execução dos loops não é uma grande preocupação, pois esses loops duram para sempre e mais tempo é gasto na seção de processamento.

Eu assumo que while (true) é mais legível do que para (;;) – sua aparência de programador erra algo em loop 🙂

e quem se importa qual é mais rápido se houver

A razão mais importante para usar “for (;;)” é o medo de usar “while (TRUE)” quando você faz uma programação exploratória. É mais fácil controlar a quantidade de repetições com “for” e também é mais fácil converter o loop “for” em um infinito.

Por exemplo, se você estiver construindo uma function recursiva, poderá limitar a quantidade de chamadas à function antes de convertê-la em um loop infinito.

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

Quando tenho certeza da minha function, então eu a converto em um loop infinito:

  for(;;) recursiveFunction(oneParam);