Colocando ponto-e-vírgula após while e instruções if em C ++

4

Como vem em C ++ quando você coloca:

while (expression);

o loop while não é executado, não importa se a expressão é verdadeira ou não.

No entanto, se você colocar:

if (expression);

a declaração é executada, não importa se a expressão é verdadeira ou não.

Parece que ambos devem se comportar da mesma maneira.

    
por Thoth 25.06.2013 / 22:09
fonte

4 respostas

14

Sua declaração que é executada (ou não) é uma instrução vazia, a ; . As outras declarações que seguem o ; não têm nada a ver com a sua declaração if e while. Seu código faria o mesmo quando escrito como

while (expression)
{
    ;
}

e

if (expression)
{
    ;
}

A única diferença é que sua declaração estaria dentro de um bloco. Você poderia adicionar mais instruções dentro do bloco (dentro das chaves) que seriam executadas, se a expressão fosse verdadeira.

    
por 25.06.2013 / 22:58
fonte
5

A sintaxe é:

if (<expr>) <statement>

// or

while (<expr>) <statement>

Portanto, a instrução (em ambos os casos) será executada apenas se a expressão for avaliada como verdadeira. No caso de while , ele entrará em um loop (reavaliando express a cada vez).

Então, a questão é o que <statement> é executado. Isso se resume à definição de declaração. Se não houver chaves {} , a próxima instrução será finalizada por ; , mesmo que essa instrução seja EMPTY . Uma declaração vazia é válida;

if (<expr>)    /* Empty Statement */;

while (<expr>) /* Empty Statement */;

Em ambos os casos, não há nada sendo executado (após a expressão ser avaliada). Embora while possa inserir um loop infinito. Nota: '{}' é um bloco de declarações (um tipo de declaração (que contém uma lista de outras declarações).

Nota:

Considera-se incorreto usar declarações vazias com for(;;) ou while() ou if() . Muitas vezes é difícil identificar e quando as pessoas o detectam, elas não têm certeza se o código está correto (e pode ter que gastar tempo para desarmar o código para verificar a exatidão).

Acho melhor usar '{}' depois de cada um deles para enfatizar o ponto (e capturar macros com várias instruções).

for(<init>;<test>;<inc>) { /*Deliberately blank */ }
    
por 26.06.2013 / 06:43
fonte
4

na verdade, quando você coloca

while(expr);

se expr for true, você entrará em um loop infinito que nunca terminará (então o código restante nunca será executado)

você pode entendê-lo substituindo a instrução vazia ; por uma não-op

void noop(){}

while(expr)noop();

então a semântica faz sentido

    
por 25.06.2013 / 22:19
fonte
1

Ambos correm, como foi apontado em outras respostas.

Considere que o concatenador de cadeias canônicas while(*s1++ = *s2++); once s1 e s2 foi inicializado. expr neste caso é *s1++ = *s2++ e o corpo do loop while é a instrução vazia ; . Lembre-se de que, em C, o valor de uma atribuição é o valor atribuído, portanto, isso pode ser reescrito como

while((*s1++ = *s2++) != 0)
{
}

e têm o mesmo efeito (com possíveis variações no desempenho, dependendo das otimizações realizadas pelo compilador).

Sua confusão provavelmente se origina do fato de que if e while são ambos seguidos por uma única instrução ou por um único bloco de instrução. Quando você coloca um terminador de declaração de ponto-e-vírgula depois da parte da condição, eles se tornam semanticamente equivalentes a:

while(expr)
{
}
{
    /* do something */
}

e

if(expr)
{
}
{
    /* do something */
}

, ambos perfeitamente válidos (você pode ter um bloco vazio ou um bloco sem uma instrução de controle de fluxo associada), mas provavelmente não faz o que deseja.

Se expr for constante , o que geralmente acontece quando nenhuma variável constituinte é modificada dentro do loop (vazio), então o loop while ignorará o bloco de instruções vazio (se expr avalia como false) ou se transforma em um loop infinito executando a instrução vazia (se expr for verdadeira).

Você pode verificar isso dando a expr um efeito colateral não-destrutivo, como registrar uma mensagem ou incrementar alguma variável estática interna ou de estado membro:

while(log_message(), expr);

e observe que a função log_message () é chamada repetidamente.

Supondo que seu código seja algo como:

int x = 0;
while (x < 1234);
{
    x++;
}
/* do more... */

agora deve ser óbvio por que seu programa não faz o que você espera, já que o acima é semanticamente equivalente a:

int x = 0;
while (x < 1234)
{
}
{
    x++;
}
/* do more... */

Como x nunca é modificado dentro do bloco de instruções do loop while (porque está vazio), a expressão x < 1234 nunca será avaliada para algo diferente de true e, portanto, você terá um loop infinito. Se a expressão fosse em vez de x != 0 , o bloco de instrução vazio seria pulado porque a condição do loop while é avaliada como false, você alcançaria o x++ e terminaria com x == 1 no ponto de /* do more... */ .

Se a condição fosse algo como ++x < 1234 , então x seria simplesmente incrementado ( ++x avaliado), e o bloco de instruções vazio executado , até que a condição seja verdadeira, após o qual o loop while termina e a execução continua com uma única passagem através do que você pretendia fazer várias vezes.

    
por 26.06.2013 / 11:47
fonte

Tags