for (;;) {
//Something to be done repeatedly
}
Já vi esse tipo de coisa ser muito usada, mas acho que é bastante estranho ... Não seria muito mais claro dizer while(true)
algo assim?
Estou supondo que (como é o motivo de muitos programadores recorrerem a códigos enigmáticos) essa é uma margem minúscula mais rápida?
Por que e realmente vale a pena? Se sim, por que não apenas defini-lo desta maneira:
#define while(true) for(;;)
Veja também: O que é mais rápido: while (1) ou while (2)?
c++
c
optimization
readability
infinite-loop
Chris Cooper
fonte
fonte
TRUE
???TRUE
tem a ver com C? A macro padrão para o verdadeiro resultado de boolen em C99 ainda étrue
. De ondeTRUE
veio isso?#define EVER ;;
tem sido utilizado em IOCCC embora .. :)#define while(TRUE)
declarar uma macro que usa um argumento chamadoTRUE
que nunca é usado, portanto, transformando cada loop while do seu programa em um loop infinito?TRUE
vem dos arquivos de cabeçalho associados à API do Windows. Não está relacionado ao VS 6.0 de forma alguma. E, como eu disse antes, não tem nada a ver com C ou C ++. No C ++, o literal "true" é justotrue
(no VS 6.0 também), no C89 / 90 não existe tal coisa e no C99 é macrotrue
. Isso se aplica a todos os compiladores C / C ++.Respostas:
fonte
Eu prefiro
for(;;)
por duas razões.Uma é que alguns compiladores produzem avisos
while(true)
(algo como "condição de loop é constante"). Evitar avisos é sempre uma boa coisa a fazer.Outra é que eu acho
for(;;)
mais claro e revelador. Eu quero um loop infinito. Literalmente não tem condição, não depende de nada. Eu só quero que continue para sempre, até que eu faça algo para sair disso.Considerando que
while(true)
, bem, o que é verdade tem a ver com alguma coisa? Não estou interessado em fazer loop até que true se torne falso, que é o que esta forma literalmente diz (faça loop enquanto true for verdadeiro). Eu só quero fazer um loop.E não, não há absolutamente nenhuma diferença de desempenho.
fonte
for(;;)
, obviamente isso parecerá estranho. Mas eu recomendo tentar se acostumar com isso, porque é um idioma comum, e você o encontrará novamente. ;)for(;condition;)
. Isso é o que um loop while é para . Mas, como eu disse, com um loop infinito, não quero que o compilador compare nenhuma condição. Ingenuamente, com umwhile
loop, ele teria que testartrue
todas as iterações (obviamente, nem mesmo o compilador mais idiota faria isso, mas é o princípio que me incomoda. Parece-me que superespecificamos seu código), enquanto com umfor(;;)
você está literalmente dizendo "não há condição para testar. Apenas faça um loop". Acho que é o mais próximo equivalente ao seu imaginárioloop {...}
while(true)
der um aviso.Pessoalmente, eu uso
for (;;)
porque não há números, é apenas uma palavra-chave. I preferem awhile (true)
,while (1)
,while (42)
,while (!0)
etc etc.fonte
true
não é mais um número mágico do quefor
uma palavra-chave mágica ou quefor(;;)
usa um infinito mágico implícito. (while (42)
É de facto abominável.)for(;;)
é analisado mais rápido do que os outros de qualquer maneira#define LIFE 42
while (LIFE)
:)while(true)
também não contém nenhum número. e para (;;) não é uma palavraPor causa de Dennis Ritchie
Comecei a usar
for (;;)
porque é assim que Dennis Ritchie o faz em K&R e, ao aprender um novo idioma, sempre tento imitar os caras espertos.Isso é C / C ++ idiomático. Provavelmente, a longo prazo, é melhor se acostumar com isso, se você planeja fazer muito no espaço C / C ++.
Você
#define
não funcionará, já que a coisa que está sendo definida deve se parecer com um identificador C.Todos os compiladores modernos geram o mesmo código para as duas construções.
fonte
while(TRUE)
, suspeito que o programador seja um novato em C ou aprendi C em um livro para leigos.Certamente não é mais rápido em nenhum compilador são. Ambos serão compilados em saltos incondicionais. A versão for é mais fácil de digitar (como Neil disse) e ficará clara se você entender a sintaxe do loop.
Se você está curioso, aqui está o que o gcc 4.4.1 me fornece para x86. Ambos usam a instrução x86 JMP .
compila para (em parte):
fonte
for_infinite
é mais rápido; 2 caracteres a menos paraputs
.Eu prefiro
for (;;)
porque é o mais consistente em diferentes idiomas do tipo C.Em C ++
while (true)
é bom, mas em C você depende de um cabeçalho para definirtrue
, mas tambémTRUE
é uma macro comumente usada. Se você usá-while (1)
lo, está correto em C e C ++ e JavaScript, mas não em Java ou C #, que exigem que a condição do loop seja booleana, comowhile (true)
ouwhile (1 == 1)
. No PHP, as palavras-chave não diferenciam maiúsculas de minúsculas, mas o idioma prefere a capitalizaçãoTRUE
.No entanto,
for (;;)
sempre está completamente correto em todos esses idiomas.fonte
for (;;)
é melhor.while (1)
efor (;;)
são expressões comuns para loops infinitos em C. Qualquer pessoa que esteja lendo um programa em C que tenha problemas para entender ou provavelmente terá problemas com o restante do código. Não é útil para escrever código C que pode ser facilmente lido por alguém que não sabe C.Pessoalmente, prefiro o
for (;;)
idioma (que será compilado com o mesmo código quewhile (TRUE)
.Usando
while (TRUE)
pode ser mais legível em um sentido, eu decidi usar ofor (;;)
idioma porque ele se destaca .Uma construção de loop infinito deve ser facilmente percebida ou destacada no código, e eu pessoalmente acho que o
for (;;)
estilo faz isso um pouco melhor quewhile (TRUE)
ouwhile (1)
.Além disso, lembro que alguns compiladores emitem avisos quando a expressão de controle de um loop while é uma constante. Não acho que isso aconteça demais, mas apenas o potencial de avisos falsos é suficiente para que eu queira evitá-lo.
fonte
Eu já vi algumas pessoas preferirem porque têm um #define em algum lugar como este:
O que lhes permite escrever isso:
fonte
FOREVER
definidafor(;;)
, mas isso não é melhor. As macros da IMO não devem ser usadas para 'inventar' um novo idioma.#define BEGIN {
e#define END }
. Eu já vi#define DONKEYS_FLY (0)
isso para que eles possam dizerif DONKEYS_FLY ...
. Quem disse que o software é chato?#define never while(0)
e#define always
E se (se o seu idioma suportar):
fonte
goto
as inúmeras desvantagens, mas, se o algoritmo que você está tentando implementar vier de um fluxograma, essa é a tradução mais direta.goto
goto
é que você não precisa se preocupar com alguém adicionando umbreak
para tornar seu loop menos infinito. (a menos que você já está dentro de outrowhile
oufor
laço é claro ...)Não há diferença em termos do código de máquina que é gerado.
No entanto, apenas para reverter a tendência, eu argumentaria 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 quaisquer outras razões pelas quais eu ' ouvi falar da abordagem for (;;) (prefiro basear minhas diretrizes de codificação em raciocínio sólido e / ou prova de eficácia).
fonte
for(;;)
é a maneira tradicional de fazer isso em C e C ++.while(true)
parece ser a convenção em C # e Java e outras linguagens. Sua milhagem pode variar.Não apenas um padrão conhecido, mas um idioma padrão em C (e C ++)
fonte
while (true)
pelo mesmo motivoif (true)
.gera um aviso com o Visual Studio (a condição é constante). Na maioria dos lugares em que trabalhei, a produção de compilação é criada com avisos como erros. assim
é preferível.
fonte
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 código de exemplo escrito no MSVC 10:
Se você construí-lo no modo Debug ( sem qualquer otimização (/ Od) ), a desmontagem mostra a clara diferença. Há instruções extras para a
true
condição internawhile
.No entanto, se você criar seu código no modo Release (com Maximize Speed (/ O2) padrão ), obterá a mesma saída para ambos. Ambos os loops são reduzidos a uma instrução de salto.
O que você usar não importa para um compilador decente com a otimização de velocidade ativada.
fonte
É uma questão de preferência pessoal para que lado é mais rápido. Pessoalmente, sou um datilógrafo e nunca olho para o meu teclado durante a programação - posso digitar todas as 104 teclas do teclado.
Acho que se for mais rápido digitar "while (TRUE)".
Eu adicionei mentalmente algumas medidas de movimento dos dedos e as totalizei. "for (;;)" possui cerca de 12 larguras de teclas dos movimentos para trás e para a quarta (entre as teclas iniciais e as teclas e entre as teclas iniciais e a tecla SHIFT) "enquanto (TRUE)" possui cerca de 14 larguras de teclas dos movimentos para trás e quarto.
No entanto, sou muito menos propenso a erros ao digitar o último. Penso mentalmente em palavras de cada vez, por isso acho mais rápido digitar coisas como "nIndex" do que acrônimos como "nIdx" porque tenho que soletrar mentalmente as letras em vez de falar dentro da minha mente e deixar meus dedos automaticamente - digite a palavra (como andar de bicicleta)
(Meu benchmark TypingTest.com = 136 WPM)
fonte
time head -10 >/dev/null
, digite cada 10 vezes e meça os resultados. Aposto que você será mais rápido, afor(;;)
menos que trapaceie. Eu estava em cerca de 14%.Todas as boas respostas - o comportamento deve ser exatamente o mesmo.
NO ENTANTO - apenas suponha que isso fez a diferença. Suponha que um deles tenha mais 3 instruções por iteração.
Você deveria se importar?
SOMENTE se o que você faz dentro do loop é quase nada , o que quase nunca acontece.
O que quero dizer é que há micro-otimização e macro-otimização. Micro-otimização é como "cortar o cabelo para perder peso".
fonte
++i
maisi++
?++i
ei++
pode ser significativa sei
for uma instância de uma classe e não um built-in e o compilador não aplicar a otimização trivial. O conselho é adquirir um hábito para que não o pegue quando for necessário.++i
vsi++
é que não custa nada fazer a "otimização". É verdade que, na maioria dos casos, não faz absolutamente nenhuma diferença, mas são igualmente fáceis de digitar; por que não preferir o potencialmente mais eficiente por padrão? E suponho que o mesmo se aplica aqui. Se um foi um pouquinho mais rápido que o outro, por que não escolher o mais rápido? O que perderíamos fazendo isso? Ambos são bastante fáceis de ler e digitar.Não consigo imaginar que um compilador que valha a pena gere qualquer código diferente. Mesmo que isso acontecesse, não haveria maneira de determinar sem testar o compilador específico que era mais eficiente.
No entanto, sugiro que você prefira
for(;;)
pelos seguintes motivos:vários compiladores que eu usei gerarão um aviso de expressão constante por enquanto (true) com as configurações apropriadas do nível de aviso.
no seu exemplo, a macro TRUE pode não ser definida como você espera
existem muitas variantes possíveis do infinito quando laço, tais como
while(1)
,while(true)
,while(1==1)
etc .; entãofor(;;)
é provável que resulte em maior consistência.fonte
while(TRUE)
avaliada comowhile(0)
provavelmente não será beneficiadafor(;;)
.while(true)
deve ser preferido em qualquer caso. Em C ++bool
é reservado e em C definido em C stdbool.h (tornando-o menos seguro em C).for(;;)
remove toda dúvida.É mais claro que:
Não que isso se aplique se você não estiver usando
Sleep()
.fonte
timerService.scheduleRepeating (50, [] () { /* lots of code */ });
O loop "para sempre" é popular em sistemas incorporados como um loop em segundo plano. Algumas pessoas o implementam como:
E às vezes é implementado como:
E ainda outra implementação é:
Um compilador de otimização deve gerar o mesmo código de montagem ou similar para esses fragmentos. Uma observação importante: o tempo de execução dos loops não é uma grande preocupação, pois esses loops duram para sempre e é gasto mais tempo na seção de processamento.
fonte
Presumo que (true) seja mais legível do que para (;;) - parece que o programador perde algo no loop for :)
fonte
O motivo mais importante para usar "for (;;)" é o medo de usar "while (TRUE)" ao executar a 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 função recursiva, poderá limitar a quantidade de chamadas para a função antes de converter em um loop infinito.
Quando tenho certeza da minha função, eu a converto em um loop infinito:
fonte