Pergunta

Eu vi alguns laços for muito estranhos ao ler o código de outras pessoas. Eu tenho tentado a procurar uma explicação sintaxe completa para o loop for em C mas é muito difícil, porque a palavra "for" aparece em frases não relacionadas tornando a busca quase impossível Google de forma eficaz.

Esta questão veio à minha mente depois de ler este discussão que me deixou curioso novamente.

O for aqui:

for(p=0;p+=(a&1)*b,a!=1;a>>=1,b<<=1);

Na condição meio há uma vírgula que separa os dois pedaços de código, o que isso vírgula fazer? A vírgula no lado direito Eu entendo como ele faz tanto a>>=1 e b<<=1.

Mas dentro de uma condição de saída loop, o que acontece? Será que sair quando p==0, quando a==1 ou quando ambos acontecer?

Seria ótimo se alguém poderia me ajudar a entender isso e talvez me apontar na direção de um for descrição completa sintaxe de loop.

Foi útil?

Solução

A vírgula não é exclusiva de loops; é o operador vírgula.

x = (a, b);

vai fazer primeiro um, em seguida b, então o conjunto de x para o valor de b.

A para a sintaxe é:

for (init; condition; increment)
    ...

O que é um pouco (ignorando continue e break por agora) equivalente a:

init;
while (condition) {
    ...
    increment;
}

Portanto, o seu, por exemplo, loop é (mais uma vez ignorando continue e break) equivalente a

p=0;
while (p+=(a&1)*b,a!=1) {
    ...
    a>>=1,b<<=1;
}

que funciona como se fosse (novamente ignorando continue e break):

p=0; 
while (true) {
    p+=(a&1)*b;
    if (a == 1) break;
    ...
    a>>=1;
    b<<=1;
}

Dois detalhes extras do loop para que não estavam na conversão simplificado para um loop while acima:

  • Se a condição for omitida, é sempre true (resultando em um loop infinito a menos que um break, goto, ou qualquer outra coisa quebra o loop).
  • A continue age como se fosse um goto a um rótulo, pouco antes do incremento, ao contrário de um continue no loop while que pular o incremento.

Além disso, um detalhe importante sobre o operador vírgula:. É um ponto de sequência, como && e || (é por isso que podem dividir-se em declarações separadas e manter o seu significado intacta)


Mudanças no C99

Os introduz padrão C99 um par de nuances não mencionados anteriormente nesta explicação (que é muito bom para C89 / C90).

Em primeiro lugar, todos os loops são blocos em seu próprio direito. Efetivamente,

for (...) { ... }

é ela própria envolvida em um par de cintas

{
for (...) { ... }
}

O sayeth padrão:

ISO / IEC 9899: 1999 §6.8.5 iteração declarações

¶5 Uma declaração iteração é um bloco cujo escopo é um subconjunto estrito do âmbito da sua encerrando bloco. O corpo do laço é também um bloco, cujo âmbito é um subconjunto estrito do escopo da declaração de iteração.

Isso também é descrito no Fundamentação em termos do conjunto extra de chaves.

Em segundo lugar, a porção init em C99 pode ser uma declaração (individual), como em

for (int i = 0; i < sizeof(something); i++) { ... }

Agora, o 'bloco envolvida em torno do loop' vem em seu próprio; isso explica porque a variável i não pode ser acessado fora do loop. Você pode declarar mais de uma variável, mas eles devem ser todos do mesmo tipo:

for (int i = 0, j = sizeof(something); i < j; i++, j--) { ... }

O sayeth padrão:

ISO / IEC 9899: 1999 §6.8.5.3 O comando for

A declaração

for ( clause-1 ; expression-2 ; expression-3 ) statement

comporta-se como se segue: A expressão-2 A expressão é a de controlo que é avaliadas antes de cada execução do corpo do laço. A expressão-3 é expressão avaliada como uma expressão nula depois de cada execução do corpo do ciclo. Se cláusula-1 é um declaração, o âmbito de quaisquer variáveis ??que ele declara é o resto da declaração e o ciclo completo, incluindo as outras duas expressões; ele é atingido na ordem de execução antes da primeira avaliação da expressão de controlo. Se cláusula-1 é uma expressão, é avaliada como uma expressão vazio antes da primeira avaliação da expressão de controlo. 133)

Ambos cláusula-1 e expressão-3 pode ser omitida. Uma expressão-2 omitido é substituído por um constante diferente de zero.

133) Assim, o ponto-1 especifica para inicialização do circuito, possivelmente declarar uma ou mais variáveis ??para uso em o laço; a expressão controlo, expressão-2, especifica uma avaliação feita antes de cada iteração, de tal modo que a execução do ciclo continua até que a expressão compara igual a 0; e express-3 especifica uma operação (tais como incrementando) que é executada após cada iteração.

Outras dicas

A vírgula simplesmente separa duas expressões e é em qualquer lugar válida em C, onde uma expressão normal é permitido. Estes são executadas em ordem, da esquerda para a direita. O valor da expressão à direita é o valor da expressão em geral.

lacetes for consistem em três partes, qualquer um dos quais pode também estar vazia; um (primeiro) é executada no início, e um (terceiro) no fim de cada iteração. Geralmente, estas peças inicializar e incrementar um contador, respectivamente; mas eles podem fazer nada.

A segunda parte é a test que é executado no início de cada execução. Se os rendimentos de ensaio false, o laço é abortada. Isso é tudo que existe para ela.

O estilo C durante circuito consiste de três expressões:

for (initializer; condition; counter) statement_or_statement_block;
  • O inicializador é executado uma vez, quando o laço começa.
  • A condição é verificada antes de cada iteração. A execução do loop enquanto ele avalia como verdadeira.
  • O contador é executado uma vez após cada iteração.

Cada uma dessas partes pode ser uma expressão válida na língua que você escrever o loop. Isso significa que eles podem ser usados ??de forma mais criativa. Qualquer coisa que você quer fazer de antemão pode ir para o inicializador, qualquer coisa que você quer fazer no meio pode ir para o estado ou o contador, até o ponto em que o circuito não tem corpo mais.

Para conseguir isso, o operador vírgula vem em muito acessível. Ele permite que você expressões cadeia para formar uma única nova expressão. Na maioria das vezes ele é usado dessa maneira em um loop, as outras implicações do operador vírgula (considerações de atribuição por exemplo valor) desempenham um papel menor.

Mesmo que você pode fazer coisas inteligentes usando a sintaxe de forma criativa - eu ficaria clara de que até eu encontrar um realmente boa razão para fazê-lo. Jogar golfe código com loops torna o código mais difícil de ler e entender (e manter).

A Wikipedia tem uma boa artigo sobre o loop for também.

Tudo é opcional em um loop for. Podemos inicializar mais de uma variável, podemos verificar se há mais de uma condição, nós iterate pode mais de uma variável usando o operador vírgula.

A seguir circuito for irá levá-lo em um loop infinito. Tenha cuidado, verificando a condição.

for(;;) 

Konrad mencionado o ponto-chave que eu gostaria de repetir:. O valor da expressão à direita é o valor da expressão geral

compilador Um Gnu afirmou este aviso quando eu coloquei dois testes na seção "condição" do loop

warning: left-hand operand of comma expression has no effect

O que eu realmente destinados à "condição" foi dois testes com um "&&" entre. Por declaração de Konrad, apenas o teste para a direita da vírgula afetaria a condição.

o loop é a execução de determinado tempo for (;;)

a Syntex de loop

for (;;)

ou

para (inicializador; condição; contador)

por exemplo (RMV = 1; RMV <= 15; RMV ++)

execução 15 vezes em para o bloco

1.Primeiro initializ o valor porque começar o valor

(por exemplo) RMV = 1 ou RMV = 2

declaração 2.Segundo é testar a condição é verdadeira ou falsa, a condição verdadeira execução tempo No.of o loop ea condição é falsa terminar para o bloco,

por exemplo i = 5, i <= 10 a condição é verdadeira

i=10;i<10 the condition is false terminate for block,

3.third é aumento ou diminuição

(por exemplo) rmv ++ ou ++ rmv

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top