For infinito sem incremento

31 respostas
J

Bom, estava lendo um certo codigo outro dia e me deparei com a seguinte instrução:

for (;;){ 
codigos e mais codigos...}

Havia um comentario do desenvolvedor dizendo que seria um loop infinito. Mas, fiquei intrigado porque na documentação do for não é obrigado a ter a instrução de incremento?
De qual outra maneira “estranha” o for pode ser usado?
Obs: Conheço o for aprimorado…

31 Respostas

Ruttmann

Tinha um for justamente desse jeito que você escreveu? Sem nenhum parâmetro?

Aguardo a opinião dos mais experientes, mas até onde eu conheço o for é um loop que tem seu “tempo de vida” muito bem definido. O papel de um loop infinito quem faz melhor seria o while.

Estou certo?

S

Johnnny8:
Bom, estava lendo um certo codigo outro dia e me deparei com a seguinte instrução:

for (;;){ 
codigos e mais codigos...}

Havia um comentario do desenvolvedor dizendo que seria um loop infinito. Mas, fiquei intrigado porque na documentação do for não é obrigado a ter a instrução de incremento?
De qual outra maneira "estranha" o for pode ser usado?
Obs: Conheço o for aprimorado…

Tendo em vista que a estrutura do for básico é:

for (inicializacao; condicao; incremento)

Até onde sei nenhuma das lacunas obriga ter declarações, posso ter além desse exemplo que você mostrou ter esses outros:

// for (var i = 0; ; ); editando... var em Java é trash, rsrsrs
for (int i = 0; ; ); // agora está correto

for ( ; i <= 10; );

for ( ; ; i++);

A questão é que declarar de qualquer uma dessas formas torna o código mais difícil de entender e mais fácil de gerar problemas.

S

Ruttmann:
Tinha um for justamente desse jeito que você escreveu? Sem nenhum parâmetro?

Aguardo a opinião dos mais experientes, mas até onde eu conheço o for é um loop que tem seu "tempo de vida" muito bem definido. O papel de um loop infinito quem faz melhor seria o while.

Estou certo?

Não necessariamente, no caso:

for ( ; ; )...

Assume um true implicito, seria a mesma coisa que isso:

for ( ; true; )...

E nesse caso como a condição nunca alcança false, torna-se infinito, o que vale também para um while.

Quanto ao papel de cada um, o while é para situações onde não sabemos quantas vezes precisamos iterar (exe: autenticar um usuário).
Já o for é utilizado para situações onde sabemos quantas vezes precisamos iterar (ex: contar os pares de 0 a 100)

Segue alguns exemplos:

Scanner scan = new Scanner(System.in);
boolean autenticou = false;

while (!autenticou) {
   System.out.print("Usuário: ");
   //String usuario = scan.next();
   String usuario = scan.nextLine(); // mais confiável
   System.out.print("Senha: ");
   // String senha = scan.next();
   String senha = scan.nextLine(); // aqui também
   
   if (usuario.equals("root") && senha.equals("123"))
      autenticou = true;
}

for (int i = 0; i <= 100; i++) {
   if (i % 2 == 0)
      System.out.println(i);
}
Ruttmann

solidsnake:
Ruttmann:
Tinha um for justamente desse jeito que você escreveu? Sem nenhum parâmetro?

Aguardo a opinião dos mais experientes, mas até onde eu conheço o for é um loop que tem seu “tempo de vida” muito bem definido. O papel de um loop infinito quem faz melhor seria o while.

Estou certo?

Não necessariamente, no caso:

for ( ; ; )...

Assume um true implicito, seria a mesma coisa que isso:

for ( ; true; )...

E nesse caso como a condição nunca alcança false, torna-se infinito, o que vale também para um while.

Ah, verdade!

Mas totalmente unusual…

:stuck_out_tongue:

S

Ruttmann:

Ah, verdade!

Mas totalmente unusual…

:P

Totalmente, eu mesmo procuro usar sempre da forma mais intuitiva possível, esses lances são bons principalmente pra certificação, mas não curto nem um pouco.

Patterson

É tem mesmo varias formas de fazer um for infinito, mas eu particularmente prefiro um while, se for para ser infinito.

tipo:

while(true){ … }

V

alias se seu objetivo é fazer um loop infinito eu recomendo você fazer assim

while(true){...}

usar o laço While junto com a instrução true deixa charo o seu objetivo que é criar um loop infinito, isso ajuda na interpretação melhor do código

S

Não podemos esquecer que uma hora ele terá de parar a iteração, seja com for, while, do while e afins, pois se isso não acontecer, pode ter certeza que o processador vai pro saco sem muito esforço.

Aliás, o autor do tópico está muito quieto, não se manifestou até agora?

Patterson

É mesmo, tem que por um Sleep pra dar um tempo para a CPU, se não no minimo o programa trava, ou pode ser um loop infinito onde tem funções dentro desse loop que esperam dados do teclado ou que ficam “escutando alguma porta” e outras varias possibilidades.

S

E na dúvida, break neles! kkkkkk

J
solidsnake:
// for (var i = 0; ; ); editando... var em Java é trash, rsrsrs
for (int i = 0; ; ); // agora está correto

for ( ; i <= 10; );

for ( ; ; i++);
Desculpe pela demora em responder... Então, quando eu declaro algum código como o citado acima, um for é complemento do outro para formar apenas 1 ou são totalmente independentes. Ex: o for de 1,2 e 3 formam o 4 ou são independentes?
//1
for (int i = 0; ; );

//2
for ( ; i <= 10; );

//3
for ( ; ; i++);

//4
for(int i = 0; i <= 10; i++){...}
Assume um true implicito, seria a mesma coisa que isso:
for(;true;);
Seguindo o raciocinio... Se o for assume um true implicitamente, quer dizer que se eu fizer um while(;); vai ser um laço de repetição infinito?
J

O que seria alem do minimo?

Me surgiu uma duvida meio “boba” aqui agora… Se não usar um sleep vamos sobrecarregar o processador…mas e a JVM… Pode se sobrecarregar ou acontecer alguma coisa do tipo? É possivel um programa “fuder” com a JVM?

Só pra constar… Estava lendo um artigo de vírus em java. Lá havia esse código aonde o autor preenchia um documento de txt infinitamente com a tentativa de sobrecarregar o HD e o processador…

S
Johnnny8:
Desculpe pela demora em responder... Então, quando eu declaro algum código como o citado acima, um for é complemento do outro para formar apenas 1 ou são totalmente independentes. Ex: o for de 1,2 e 3 formam o 4 ou são independentes?
//1
for (int i = 0; ; );

//2
for ( ; i <= 10; );

//3
for ( ; ; i++);

//4
for(int i = 0; i <= 10; i++){...}

Não confunda as coisas... eles integram ou são separados com base no corpo de cada um.

Perceba que para cada for que declarei existe um ponto-vírgula no final. Essa forma quer dizer que todos os 4 são independentes.

Agora como cada um deles não tem {} não quer dizer que não tem um corpo entende? O corpo de cada um deles é o ;

Ou seja, é um corpo sem instrução, apenas para tentar explicar a sua dúvida anterior quanto ao cabeçalho do for.

Se eu quisesse aninhá-los (declarar um dentro do outro) teria de ser dessa forma:

for (int i = 0; i <= 10; i++)
   for (int j = 0; j <= 5; j++)
      for (int k = 0; k <= 2; k++)
         System.out.println("i = " + i + ", j = " + j + ", k = " + k);

Para reforçar, seria a mesma coisa que isso:

for (int i = 0; i <= 10; i++) {
   for (int j = 0; j <= 5; j++) {
      for (int k = 0; k <= 2; k++) {
         System.out.println("i = " + i + ", j = " + j + ", k = " + k); // opa aqui já tem
      }
   }
}
E para reforçar mais ainda o primeiro caso do ponto-virgula:
for (int i = 0; i <= 10; i++)
   ;

for (int j = 0; j <= 5; j++)
   ;
    
for (int k = 0; k <= 2; k++)
   ;

Que seria a mesma coisa que isso:

for (int i = 0; i <= 10; i++) {

}

for (int j = 0; j <= 5; j++) {

}
    
for (int k = 0; k <= 2; k++) {

}

Há várias formas de se declarar laços, isso também vale para if, if-else, switch/case etc.

Johnnny8:
Assume um true implicito, seria a mesma coisa que isso:
for(;true;);
Seguindo o raciocinio... Se o for assume um true implicitamente, quer dizer que se eu fizer um while(;); vai ser um laço de repetição infinito?

Seguindo o raciocínio de que cada ponto e vírgula é um fim de instrução, o for aceita três tipos de instrução lembra lá no meu primeiro post:

for (inicializacao; condicao; incremento);

Ou seja, dentro de um laço posso ter no máximo três instruções correto? Por isso tenho de separá-las com ;

O while possui apenas um tipo de instrução:

while (condicao);

Logo não preciso/posso declarar o ;

Outra coisa é que no caso do while ele obriga você declarar a instrução, então:

while ()

Não é válido, ele precisa saber se é true ou false.

Cara desculpe o post tão grande, mas é que você ficou muito tempo sem responder e agora está querendo tirar suas dúvidas de uma vez só, isso confunde até a gente, rsrsrs, mas espero ter sido mas claro agora.

J


Ou seja, dentro de um laço posso ter no máximo três instruções correto?

Correto.

Só mais uma pergunta…
Quando eu faço:

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

O for contará de 0 a 1000 mesmo não tendo nada para ele executar?

Li em algum livro…
Não me lembro ao certo mas… parece que o java pula a instrução e no C executa até 1000… O C é mais rapido mas o java é mais inteligente… é isso mesmo?

Muito obrigado pela boa vontade em responder solidsnake, victor, patterson e ruttman. Que bom que existem pessoas de boa vontade aqui no Guj como vocês…

S

Johnnny8:

Ou seja, dentro de um laço posso ter no máximo três instruções correto?

Correto.

Só mais uma pergunta…
Quando eu faço:

for(int i = 0; i &lt;= 1000; i++);

O for contará de 0 a 1000 mesmo não tendo nada para ele executar?

Li em algum livro…
Não me lembro ao certo mas… parece que o java pula a instrução e no C executa até 1000… O C é mais rapido mas o java é mais inteligente… é isso mesmo?

Muito obrigado pela boa vontade em responder solidsnake, victor, patterson e ruttman. Que bom que existem pessoas de boa vontade aqui no Guj como vocês…

Isso mesmo, devido o compilador sempre checar o código antes de compilá-lo, ele busca deixar seu código mais performático, assim ele acaba corrigindo algumas coisas que ele acha inviável como por exemplo o "laço sem corpo" no exemplo acima.

Ele deve pensar assim: Pô, qual sentido o programador declarou um for pra rodar mil vezes se ele não tem corpo, eu vou é "muquiar" essa treta aqui… kkkkk

V

Johnnny8:

Ou seja, dentro de um laço posso ter no máximo três instruções correto?

Correto.

Só mais uma pergunta…
Quando eu faço:

for(int i = 0; i &lt;= 1000; i++);

O for contará de 0 a 1000 mesmo não tendo nada para ele executar?

Li em algum livro…
Não me lembro ao certo mas… parece que o java pula a instrução e no C executa até 1000… O C é mais rapido mas o java é mais inteligente… é isso mesmo?

Muito obrigado pela boa vontade em responder solidsnake, victor, patterson e ruttman. Que bom que existem pessoas de boa vontade aqui no Guj como vocês…

olha até onde sei uma instrução é sempre uma instrução mesmo que ela seja redundante ou inútil como seria esse caso, e o mesmo ocorre em c;

quero dizer que se o programador quiser colocar ele coloca.

Por exemplo muitas vesses eu tenho o costume (mais em php) mas também faço em java de pegar uma variável booleana e verificar se ela é true assim :

boolean hue = true; if(hue == true){ }

eu faço isso para deixar explicito no código minha intenção (de certa forma chega a ser uma documentação) mas eu faço isso mais em php mas sabe como é o costumo de cachimbo deixa a boca torta.

Mesmo assim esse tipo de instrução o java vai ter mais trabalho talvez 1 nano segundo a mais, mas ele vai trabalhar a mais

Vynko

O interessante para descobrir se o java é realmente “inteligente” como você citou, seria declarar uma variável anteriormente e usá-lá só após o for. Vamos ver se funciona :]

class app{
	public static void main(String[] args){
		int i;
		for(i=0; i<1000; i++);
		System.out.println(i);
		if(i==1000){
			System.out.println("Que decepcao, merece umas palmadas.");
		}else{
			System.out.println("Java é inteligente!");
		}
	}
}

Retornaria: http://snag.gy/DNpnr.jpg
Acho que java mereçe umas palmadas kk’

V

não disse, uma instrução é sempre uma instrução, mesmo sendo inútil

Vynko

Não é inútil caso use uma variável já existente, mas se o java identificasse que foi criado uma nova variável, que terminasse naquele corpo do for(como sempre), e não tivesse realmente função nenhuma, não teria para que realizar a ação, mas é bom saber que os desenvolvedores não foram tolos o bastante para perder tempo com uma característica tão banal como essa, LOL

ViniGodoy

Tanto o Java, quanto o C, implementam uma otimização de compilador chamada dead code elimination. Ou seja, comandos vazios (fors, ifs, whiles, etc) são eliminados.

O teste ali não funciona pois essa otimização funciona se, E SOMENTE SE, não houver código dentro do for (alguns códigos, como uma declaração de variável sem que não se faça nada com ela, também são solenemente ignorados).

Se o for tiver qualquer efeito prático, ele vai ficar no código (e nem poderia ser diferente).

Em termos de otimização de compilador, tanto o Java quanto o C são bastante agressivos. Principalmente se, no caso do C, a opção O3 estiver ligada.

ViniGodoy

Outra situação bizarra do for é usa-lo com duas variáveis.

for(int i=0,int j=10; i &lt; 5 && j &gt; 0; i++ , j--) { }

Vynko

Compreendo apartir disso que o for é mais útil ao utilizar uma ou mais variáveis, seria um pouco cansativo programar o mesmo código dentro do while;

int i=0;
int j=10;
while(i<5){
	i++;
}while(j>0){
	j--;
}

E se quiséssemos utilizar os whiles encadeados, teríamos que modificar um pouco o código;

int i=0;
int j=10;
while(j>0){
	while(i<5){
		i++;
	}j--;
}

Realmente, existem grandes diferenças between for e while =}, nesse caso, while seria uma opção inviável.
A propósito, acho que a dúvida do nosso amigo já está resolvida, vamos esperar uma resposta dele.

Patterson

Então no C eu sei que ele conta até Mil mesmo sem nenhum código dentro do for, já no Java eu não sei ao certo.

Mas acho que pode ter as vantagens no C fazer isso, por isso C é uma das linguagens mais usadas para fazer malwares, daqueles que acaba com a memória e trava seu PC, agora o Java foi feito para evitar essas coisas, por que muitas veses alguem pode errar e fazer um codigo que vai travar o programa, como acontece com os ponteiros de C e C++, o java nem tem ponteiros explicitos por causa disso. Tente executar um for desses para ver se o java conta ou não.
Falou!!

ViniGodoy

O C só faz isso se você desabilitar todas as opções de otimização do compilador, o que é uma idiotice (por padrão, os compiladores usam o1 ou o2).
De maneira geral, deadcode elimination é uma estratégia de otimização bem simples e mesmo compiladores C muito rudimentares a implementam.

ViniGodoy

Não tem nada a ver. Alguns compiladores C são extremamente inteligentes, e extremamente otimizados e muitíssimo inteligentes. Especialmente os compiladores profissionais de mercado, como o Visual Studio e o GCC. Há, inclusive, compiladores específicos para aproveitar ao máximo certos compiladores, como é o caso do compilador da Intel.

As diferenças reais de performance ocorrem em outros campos:
a) Alocação de memória. Como foi falado ali, o Java utiliza garbage collection, dando ao programador apenas acesso indireto a memória. O algoritmo do garbage collector é bastante eficiente e “tunado” para aplicações comerciais de maneira geral. O C e o C++ utilizam alocação direta. Não há nenhuma estratégia inteligente na alocação direta, portanto, ela é pouquíssimo eficiente. Entretanto, ele dá a possibilidade de você usar memória stack diretamente (que é muito veloz) e dá a possibilidade de você implementar seu próprio alocador o que, apesar de difícil, pode ser bem mais otimizado do que o garbage collector jamais fará.

b) Compilação just-in-time: O código Java é compilado no momento da execução. Isso tem a vantagem do compilador poder usar instruções específicas da máquina para onde o programa java está executando. Como a compilação do C e do C++ é prévia, você não pode usar otimizações realmente agressivas sem limitar as plataformas de seu programa. Entretanto, a compilação just-in-time tem um custo para o Java. Ele precisa ficar constantemente analisando os métodos mais chamados (hotspots) e só então realizar essa compilação. Todo o processo tem impacto de performance em Runtime.

Há outros problemas a serem considerados:
a) O garbage collector é consome mais memória do que a alocação direta. Consideravelmente mais.
b) A execução do garbage collector congela o programa java por alguns microssegundos. Não é problema na maior parte de aplicações comerciais, mas é nas aplicações multimídia. Você nunca sabe quando o gc vai rodar.

Se quiser ler a fundo sobre como o java funciona, e entender melhor como os dois se comparam leia os artigos do Brian Goetz:

Tunning Garbage Collection With JVM 5: http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html

E

ViniGodoy:
Outra situação bizarra do for é usa-lo com duas variáveis.

for(int i=0,int j=10; i &lt; 5 && j &gt; 0; i++ , j--) { }

Não é bizarro se todo mundo se lembrar que

for (A; B; C) {
   d;
   e;
}

equivale sempre a:

{
    A;
    while (B) {
       d;
       e;
       C;
    }
}

No caso do exemplo do Vinigodoy (que a propósito tem só um errinho), o código equivalente tem apenas 1 (UM) while, não 2 como o Vynko achou.
O código corrigido do Vinigodoy é:

for(int i=0, j=10; i &lt; 5 && j &gt; 0; i++, j--) {  
    ...
}

Que é equivalente a:

{
    int i=0, j=10; 
    while (i &lt; 5 && j &gt; 0) {
       ...
       i++;
       j--;
    }
}
ViniGodoy

Sim, é por essas e outras que evito esse tipo de construção. Além de difícil de ler, não é usual.

Outra situação interessante do for é que ele não precisa necessariamente ser usado com variáveis numéricas:

for ( Iterator&lt;String&gt; it = exemplo.iterator(); it.hasNext(); ) { System.out.println( it.next() ); }

Eu sou bem conservador no uso do for. Geralmente só para o caso básico mesmo, com uma única variável contadora. Nem que isso gere um pouco mais de código.

E

Como o for é um while disfarçado, mas seu uso é sempre para percorrer alguma coleção, eu gosto de escrever o seguinte código:

BufferedReader br = new BufferedReader (new FileReader ("...."));
for (String linha = br.readLine(); linha != null; linha = br.readLine()) {
    ...
}

para enfatizar que estou percorrendo todas as linhas do arquivo, em vez de usar o código mais comum e que lembra código C (e que gera um readLine a menos, ha ha ha) :

BufferedReader br = new BufferedReader (new FileReader ("...."));
while ((linha = br.readLine()) != null) {
    ...
}

Não gosto muito de fazer atribuições dentro da condição de um while - fora o fato de que é muito C pro meu gosto, sempre há aquele maldito problema de escrever um “=” a mais ou a menos.

E

Se as pessoas aprenderem que “for” é para percorrer coleções, será fácil para elas transformarem seu código naquelas construções que são muito comuns em linguagens funcionais, como “map” ou “reduce” ou “apply” ou “flatten” ou “fold” ou “zip” - por exemplo, http://www.scala-lang.org/api/current/index.html#scala.collection.Map

Vynko

Você errou uma coisa amigo, eu acho, o && faria com que quando o i se tornasse 5, o loop pararia, se estou correto… Mas por outro lado você está certo, utilizar o ||(invéz do &&) não teria necessidade nenhuma do meu patético código usando 2 whiles xD

WellingtonRamos

Um improvável enriquecimento do assunto surgiu neste tópico no momento que passou-se a considerar otimizações de compilação. Muito bom :slight_smile:

Criado 8 de julho de 2013
Ultima resposta 10 de jul. de 2013
Respostas 31
Participantes 9