Inserimento di punti e virgola dopo un istante e se le istruzioni in C ++

4

Come mai in C ++ quando metti:

while (expression);

il ciclo while non viene eseguito, non importa se l'espressione è vera o no.

Comunque se metti:

if (expression);

l'istruzione viene eseguita indipendentemente dall'espressione vera o meno.

Sembra che entrambi dovrebbero comportarsi allo stesso modo.

    
posta Thoth 25.06.2013 - 22:09
fonte

4 risposte

14

L'istruzione che viene eseguita (o meno) è un'istruzione vuota, ; . Le altre istruzioni che seguono ; non hanno nulla a che fare con la tua istruzione if e while. Il tuo codice farebbe lo stesso quando scritto come

while (expression)
{
    ;
}

e

if (expression)
{
    ;
}

L'unica differenza è che la tua affermazione sarebbe all'interno di un blocco. Potresti aggiungere più istruzioni all'interno del blocco (all'interno delle parentesi graffe) che verrebbero eseguite, se l'espressione era vera.

    
risposta data 25.06.2013 - 22:58
fonte
5

La sintassi è:

if (<expr>) <statement>

// or

while (<expr>) <statement>

Quindi l'istruzione (in entrambi i casi) viene eseguita solo se l'espressione è vera. Nel caso di while entrerà in un ciclo (rivalutazione espressa ogni volta).

Quindi la domanda su quale <statement> viene eseguita. Questo si riduce alla definizione di affermazione. Se non ci sono parentesi graffe {} , l'istruzione successiva viene terminata da ; anche se tale istruzione è EMPTY . Un'istruzione vuota è valida;

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

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

In entrambi i casi non viene eseguito nulla (dopo che l'espressione è stata valutata). Sebbene while possa entrare in un ciclo infinito. Nota: '{}' è un'istruzione-Block (un tipo di istruzione (che contiene un elenco di altre istruzioni).

Nota:

È considerato una cattiva forma utilizzare istruzioni vuote con for(;;) o while() o if() . È spesso difficile da individuare e quando le persone lo individuano non sono del tutto sicuro che il codice sia corretto (e potrebbe dover dedicare del tempo a smascherare il codice per verificarne la correttezza).

Trovo che sia meglio usare '{}' dopo ognuno di questi per enfatizzare il punto (e catturare macro multi = statement).

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

in realtà quando metti

while(expr);

quindi se expr è vero, si entra in un ciclo infinito che non finirà mai (quindi il codice rimanente non viene mai eseguito)

puoi capirlo sostituendo l'istruzione vuota ; con un no-op

void noop(){}

while(expr)noop();

quindi la semantica ha senso

    
risposta data 25.06.2013 - 22:19
fonte
1

Corrono entrambi, come è stato sottolineato in altre risposte.

Considera il concatenatore di corde canonico while(*s1++ = *s2++); una volta s1 e s2 sono stati inizializzati. expr in questo caso è *s1++ = *s2++ e il corpo del ciclo while è l'istruzione vuota ; . Ricorda che in C, il valore di un'assegnazione è il valore assegnato, quindi questo potrebbe essere riscritto come

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

e hanno lo stesso effetto (con possibili variazioni nelle prestazioni a seconda delle ottimizzazioni eseguite dal compilatore).

Probabilmente la tua confusione deriva dal fatto che if e while sono entrambi seguiti da una singola istruzione o da un singolo blocco di istruzioni. Quando si inserisce un terminatore di istruzione punto e virgola dopo la parte condition, diventano semanticamente equivalenti a:

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

e

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

che sono entrambi codici perfettamente validi (puoi avere un blocco vuoto o un blocco senza un'istruzione di controllo di flusso associata) ma probabilmente non fare ciò che vuoi.

Se expr è costante , che è spesso il caso in cui nessuna variabile costitutiva viene modificata nel ciclo (vuoto), allora il ciclo while salterà il blocco di istruzioni vuoto (se expr restituisce false) o diventa un ciclo infinito eseguendo l'istruzione vuota (se expr restituisce true).

Puoi verificarlo dando a expr un effetto collaterale senza interruzioni, come la registrazione di un messaggio o l'incremento di alcune variabili interne statiche o di stato membro:

while(log_message(), expr);

e osserva che la funzione log_message () viene chiamata ripetutamente.

Supponendo che il tuo codice sia qualcosa del tipo:

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

ora dovrebbe essere ovvio il motivo per cui il tuo programma non fa quello che ti aspetti, in quanto quanto sopra è semanticamente equivalente a:

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

Poiché x non viene mai modificato all'interno del blocco di istruzioni del ciclo while (poiché è vuoto), l'espressione x < 1234 non valuterà mai nulla di diverso da vero, e quindi avrai un ciclo infinito. Se invece l'espressione fosse x != 0 , il blocco di istruzioni vuoto verrà saltato perché la condizione del ciclo while viene valutata come false, si raggiungerà x++ e si concluderà con x == 1 nel punto di /* do more... */ .

Se la condizione era invece qualcosa come ++x < 1234 , allora x sarebbe semplicemente incrementato ( ++x valutato), e il blocco di istruzioni vuoto eseguito , finché la condizione non è vera, dopo di che il ciclo while termina e l'esecuzione continua con un singolo passaggio attraverso ciò che intendi fare un certo numero di volte.

    
risposta data 26.06.2013 - 11:47
fonte

Leggi altre domande sui tag