Versão longa...
Um colega de trabalho afirmou hoje depois de ver meu uso while (1)
em um script Perl que for (;;)
é mais rápido. Argumentei que eles deveriam ser os mesmos, esperando que o intérprete otimize quaisquer diferenças. Configurei um script que executaria 1.000.000.000 de iterações de loop e o mesmo número de loops while e registrei o tempo entre eles. Não pude encontrar nenhuma diferença apreciável. Meu colega de trabalho disse que um professor havia dito que ele while (1)
estava fazendo uma comparação 1 == 1
e que for (;;)
não estava. Repetimos o mesmo teste com 100x o número de iterações com C ++ e a diferença foi insignificante. No entanto, foi um exemplo gráfico de quão rápido o código compilado pode ser em comparação com uma linguagem de script.
Versão curta...
Existe alguma razão para preferir um while (1)
over a for (;;)
se você precisar de um loop infinito para sair?
Nota: Se não estiver claro a partir da pergunta. Essa foi uma discussão acadêmica puramente divertida entre dois amigos. Estou ciente de que este não é um conceito super importante que todos os programadores deveriam agonizar. Obrigado por todas as ótimas respostas que eu (e tenho certeza que outros) aprendemos algumas coisas com essa discussão.
Atualização: O colega de trabalho acima mencionado pesou com uma resposta abaixo.
Citado aqui, caso seja enterrado.
Ele veio de um programador de montagem AMD. Ele afirmou que os programadores C (o povo) não percebem que seu código tem ineficiências. Ele disse hoje que os compiladores gcc são muito bons e colocam pessoas como ele fora do negócio. Ele disse, por exemplo, e me contou sobre o
while 1
vsfor(;;)
. Eu o uso agora por hábito, mas o gcc e especialmente os intérpretes farão a mesma operação (um salto no processador) nos dois dias, pois eles são otimizados.
fonte
Respostas:
No perl, eles resultam nos mesmos opcodes:
Da mesma forma no GCC:
Então, acho que a resposta é que são iguais em muitos compiladores. Obviamente, para alguns outros compiladores, isso pode não ser necessariamente o caso, mas é provável que o código dentro do loop seja alguns milhares de vezes mais caro do que o próprio loop, então quem se importa?
fonte
Usando o GCC, os dois parecem compilar para a mesma linguagem assembly:
fonte
Não há muitas razões para preferir um ao outro. Eu acho que,
while(1)
particularmente,while(true)
são mais legíveis do quefor(;;)
, mas essa é apenas a minha preferência.fonte
forever
é seu próprio token.Não há diferença de acordo com o padrão. 6.5.3 / 1 tem:
E 6.5.3 / 2 tem:
Portanto, de acordo com o padrão C ++, o código:
é exatamente o mesmo que:
fonte
O compilador Visual C ++ usado para emitir um aviso para
(expressão constante), mas não para
Continuei a prática de preferir
for (;;)
por esse motivo, mas não sei se o compilador ainda faz isso atualmente.fonte
for(;;)
é um caractere a menos para digitar, se você quiser ir nessa direção para otimizar as coisas.fonte
O Turbo C com esses compiladores antigos
for(;;)
resulta em um código mais rápidowhile(1)
.Hoje, os compiladores gcc, Visual C (acho que quase todos) otimizam bem, e CPUs com 4,7 MHz raramente são usadas.
Naqueles dias, a
for( i=10; i; i-- )
era mais rápida do quefor( i=1; i <=10; i++ )
, porque a comparaçãoi
é 0, resulta em um salto condicional de CPU-Zero-Flag. E o Zero-Flag foi modificado com a última operação de decremento( i-- )
, nenhuma operação extra de cmp é necessária.e aqui com
for(i=1; i<=10; i++)
cmpl extra:fonte
Para todas as pessoas que discutem, você não deve usar indefinte enquanto faz loops e sugerir coisas idiotas, como usar goto aberto (sério, ai)
Realmente não pode ser representado efetivamente de nenhuma outra maneira. Não sem criar uma variável de saída e fazer magia negra para mantê-la sincronizada.
Se você tem uma inclinação para a sintaxe mais goto-esque, use algo sensato que limite o escopo.
Em última análise, a velocidade não é tão importante
Preocupar-se com a eficácia da velocidade das diferentes estruturas de loop é um enorme desperdício de tempo. Otimização prematura por completo. Não consigo pensar em nenhuma situação que já vi em que o código de perfil encontrou gargalos na minha escolha de construção de loop.
Geralmente é o como do loop e o quê do loop.
Você deve "otimizar" a legibilidade e a sucessão e escrever o que for melhor para explicar o problema ao próximo otário pobre que encontrar seu código.
Se você usar o truque "goto LABEL" que alguém mencionou, e eu tiver que usar seu código, esteja preparado para dormir com um olho aberto, especialmente se você fizer isso mais de uma vez, porque esse tipo de coisa cria um código espaguete horrível .
Só porque você pode criar código espaguete não significa que você deve
fonte
De Stroustrup, TC ++ PL (3a edição), §6.1.1:
Eu prefiro
for (;;)
.fonte
Se o compilador não fizer nenhuma otimização,
for(;;)
sempre será mais rápido quewhile(true)
. Isso ocorre porque a instrução while avalia a condição toda vez, mas a instrução for é um salto incondicional. Mas se o compilador otimizar o fluxo de controle, ele poderá gerar alguns códigos de operação. Você pode ler o código de desmontagem com muita facilidade.PS, você pode escrever um loop infinito como este:
fonte
Eu ouvi sobre isso uma vez.
Ele veio de um programador de montagem AMD. Ele afirmou que os programadores C (as pessoas) não percebem que seu código tem ineficiências. Ele disse hoje que os compiladores gcc são muito bons e colocam pessoas como ele fora do negócio. Ele disse, por exemplo, e me contou sobre o
while 1
vsfor(;;)
. Eu o uso agora por hábito, mas o gcc e especialmente os intérpretes farão a mesma operação (um salto no processador) nos dois dias, pois eles são otimizados.fonte
Em uma construção otimizada de uma linguagem compilada, não deve haver diferença apreciável entre os dois. Nenhum deles deve terminar comparando em tempo de execução; eles apenas executarão o código do loop até você sair manualmente do loop (por exemplo, com a
break
).fonte
Estou surpreso que ninguém testou corretamente
for (;;)
contra owhile (1)
perl!Como o perl é uma linguagem interpretada, o tempo para executar um script perl não consiste apenas na fase de execução (que neste caso é a mesma), mas também na fase de interpretação antes da execução. Ambas as fases devem ser levadas em consideração ao fazer uma comparação de velocidade.
Felizmente, o perl possui um módulo Benchmark conveniente , que podemos usar para implementar um benchmark, como a seguir:
Observe que estou testando duas versões diferentes do loop for infinito: uma que é mais curta que o loop while e outra que possui um espaço extra para torná-lo com o mesmo comprimento do loop while.
No Ubuntu 11.04 x86_64 com perl 5.10.1, recebo os seguintes resultados:
O loop while é claramente o vencedor nesta plataforma.
No FreeBSD 8.2 x86_64 com perl 5.14.1:
Enquanto loop é o vencedor aqui também.
No FreeBSD 8.2 i386 com perl 5.14.1:
Surpreendentemente, o loop for com um espaço extra é a escolha mais rápida aqui!
Minha conclusão é que o loop while deve ser usado na plataforma x86_64 se o programador estiver otimizando a velocidade. Obviamente, um loop for deve ser usado ao otimizar espaço. Infelizmente, meus resultados são inconclusivos em relação a outras plataformas.
fonte
Benchmark
tem suas limitações e não pode ser usado para distinguir rápido de lento se os resultados estiverem dentro de 7% um do outro. Além disso, você não testou a diferença entre os loopsfor
ewhile
porque cada subdie
antes de atingir os loops. E desde quando a quantidade de espaço em branco importava para o intérprete Perl? Desculpe, mas a análise é extremamente falha.die
Existe no meu código porque minha intenção é testar apenas a diferença de tempo de compilação . Como outros já apontaram, o código de bytes resultante é idêntico, portanto, não faz sentido testar isso. Surpreendentemente, a quantidade de espaço em branco parece fazer uma pequena diferença nesse caso nos meus ambientes de teste. Poderia ter algo a ver com a forma como os personagens acabam ficando alinhado na memória ou algo semelhante ...Benchmark
são inconclusivos. Não confie nessa diferença de 1%!-60
executa o teste por 60 segundos.Em teoria, um compilador completamente ingênuo poderia armazenar o literal '1' no binário (desperdiçando espaço) e verificar se 1 == 0 a cada iteração (desperdiçando tempo e mais espaço).
Na realidade, no entanto, mesmo com otimizações "não", os compiladores ainda reduzirão os dois para o mesmo. Eles também podem emitir avisos porque podem indicar um erro lógico. Por exemplo, o argumento de
while
poderia ser definido em outro lugar e você não percebe que é constante.fonte
Estou surpreso que ninguém tenha oferecido a forma mais direta, correspondente à montagem desejada:
fonte
{ forever: do stuff; goto forever; }
)while(1)
é um idiomafor(;;)
reconhecido pela maioria dos compiladores.Fiquei feliz em ver que perl também reconhece
until(0)
.fonte
Para resumir o
for (;;)
vswhile (1)
debate Nos compiladores, esses ganhos são otimizados, pois, com o fato de que o último é mais fácil de entender do que o primeiro, acredito que seria mais preferível.fonte
Acabei de encontrar esse tópico (apesar de alguns anos atrasado).
Acho que encontrei a verdadeira razão pela qual "para (;;)" é melhor que "enquanto (1)".
de acordo com o "padrão de codificação barr 2018"
Basicamente, esse não é um problema de velocidade, mas de legibilidade. Dependendo da fonte / impressão do código, o número um (1) em algum momento pode parecer uma letra minúscula l.
ie 1 vs l. (em algumas fontes, elas parecem idênticas).
Assim, while (1) pode parecer um loop while dependente da variável letra L.
while (true) também pode funcionar, mas em alguns casos mais antigos de C e C incorporados, true / false ainda não estão definidos, a menos que stdbool.h esteja incluído.
fonte
l
, não isso1
el
pode parecer semelhante.Eu pensaria que ambos são iguais em termos de desempenho. Mas eu preferiria o (1) para facilitar a leitura, mas questiono por que você precisa de um loop infinito.
fonte
Eles são os mesmos. Há questões muito mais importantes a serem ponderadas.
Meu argumento, que foi implícito, mas não explicitamente mencionado acima, é que um compilador decente geraria exatamente o mesmo código para ambas as formas de loop. O ponto mais importante é que a construção de loop é uma parte menor do tempo de execução de qualquer algoritmo, e você deve primeiro garantir que otimizou o algoritmo e tudo o mais relacionado a ele. A otimização da construção do loop deve estar absolutamente no final da sua lista de prioridades.
fonte