Menu

Break e continue in C: come funzionano e quando usarli

break esce da un ciclo o da uno switch; continue salta al passaggio successivo. Come si comportano in for, while e do-while, come uscire da cicli annidati con un flag o goto, e gli abusi che rendono i cicli difficili da seguire.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

Due modi per cambiare il flusso di un ciclo

La condizione di un ciclo decide quando finisce, ma a volte la vera risposta arriva a metà del corpo. Stai cercando in un array e trovi l'elemento al terzo posto: perché controllare gli altri 997? Oppure stai elaborando una lista e una voce è vuota: saltala e vai avanti.

C ha una parola chiave per ciascun caso:

  • break: esci subito dal ciclo. L'esecuzione riprende dalla prima istruzione dopo il ciclo.
  • continue: abbandona solo questo passaggio. Passa al successivo.

Il primo ciclo stampa 1 2 3 4 e si ferma. Il secondo stampa 1 2 3 4 6 7 8 9 10: ha saltato un valore ed è andato avanti.

break in un ciclo

L'uso tipico è una ricerca che si ferma appena ha successo:

Poiché found viene impostato prima del break, il codice dopo il ciclo può distinguere tra "trovato" e "elementi finiti". Questa coppia, una variabile risultato più un break, è l'idioma di ricerca standard in C. Il contatore del ciclo invece non è utilizzabile dopo, se è dichiarato nell'intestazione, perché esce dallo scope alla graffa di chiusura.

break esce sempre da un solo ciclo: il for, while, do-while o switch più vicino che lo racchiude.

continue in un ciclo

continue serve per le voci da saltare senza interrompere il lavoro:

Dove salta continue dipende dal ciclo:

for        -> la parte di aggiornamento dell'intestazione (il contatore avanza comunque)
while      -> il test della condizione (il resto del corpo non viene eseguito)
do-while   -> il test della condizione in fondo

Questa differenza non è teorica. In un ciclo for, continue non può mai saltare l'incremento del contatore, perché l'incremento sta nell'intestazione. In un ciclo while sì:

/* BUG: continue salta i++, quindi si blocca al primo numero pari */
int i = 0;
while (i < 10) {
    if (i % 2 == 0) {
        continue;
    }
    printf("%d ", i);
    i++;
}

Sposta i++ sopra il continue, oppure scrivilo come ciclo for, dove l'intestazione rende impossibile sbagliare.

Un break nello switch non è un break del ciclo

break termina il ciclo o lo switch più vicino che lo racchiude, quello dei due che è più vicino. Metti uno switch dentro un ciclo e ogni break al suo interno appartiene allo switch:

Il comando q stampa il suo messaggio e il ciclo continua con cc. Se l'uscita doveva terminare il ciclo, quel break non l'ha fatto. Le soluzioni sono un flag, un goto oppure spostare il ciclo in una funzione e usare return: le vedi tutte qui sotto.

Uscire da cicli annidati

Un singolo break esce da un solo livello. Dentro due cicli annidati termina solo quello interno, e il ciclo esterno inizia il passaggio successivo come se nulla fosse.

C non ha break 2 né break con etichetta. Tre opzioni oneste:

Un flag. Portabile, ovvio e un po' rumoroso:

Il flag compare in due punti, la condizione esterna e l'assegnazione, e questo è il costo. Con tre livelli di annidamento diventa davvero sgradevole.

goto. Il tanto criticato salto di C, e questo è l'unico caso in cui i programmatori C esperti lo usano senza scusarsi:

Un goto in avanti verso un'etichetta subito dopo i cicli fa esattamente quello che farebbe un break con etichetta in altri linguaggi, in una riga e senza flag da tenere sincronizzati. La reputazione di goto deriva dai salti all'indietro e dai salti nel mezzo di altri blocchi, che producono davvero un flusso di controllo illeggibile. Un singolo salto in avanti fuori da cicli annidati non è questo. Il kernel Linux usa lo stesso schema per i percorsi di pulizia. Usalo in modo consapevole e con parsimonia; non lasciare che il tabù ti spinga verso un'alternativa con tre flag più difficile da leggere.

Una funzione e return. Di solito la risposta migliore, perché una ricerca merita un nome:

return esce da tutti i cicli della funzione, non richiede flag né etichette, e il codice di ricerca ora ha un nome e può essere testato da solo. Quando l'annidamento è così profondo che uscirne diventa un problema, spesso è un segnale che quel blocco voleva comunque essere una funzione.

Quando aiutano e quando fanno danni

break e continue si guadagnano il loro posto quando permettono a un ciclo di dire "questo caso è finito" una volta sola, in alto, invece di avvolgere tutto il corpo in un if. Confronta:

/* con continue: il lavoro vero non è indentato */
for (int i = 0; i < n; i++) {
    if (!isValid(a[i])) continue;
    if (isDuplicate(a[i])) continue;
    process(a[i]);
}

/* senza: ogni controllo aggiunge un livello */
for (int i = 0; i < n; i++) {
    if (isValid(a[i])) {
        if (!isDuplicate(a[i])) {
            process(a[i]);
        }
    }
}

Fanno danni quando sono troppi. Un ciclo con cinque break sparsi e tre continue ha una condizione di uscita che non è scritta da nessuna parte: chi legge deve simulare l'intero corpo per sapere quando si ferma. Due linee guida che reggono bene: tieni i controlli con continue tutti insieme in cima al corpo e, se un ciclo ha più di uno o due break, chiediti se quel lavoro non dovesse farlo la condizione nell'intestazione.

Due trappole minori. continue in un do-while salta al test in fondo, che è comunque la cosa successiva: innocuo, ma sorprende. E break fuori da qualsiasi ciclo o switch è un errore di compilazione, l'unico sbaglio di questa pagina che il compilatore individua al posto tuo.

Domande frequenti

Qual è la differenza tra break e continue in C?

break termina del tutto il ciclo e l'esecuzione riprende dopo di esso. continue abbandona solo il passaggio corrente e passa al successivo: all'aggiornamento in un ciclo for, oppure direttamente al test della condizione in un while o do-while.

Come si esce da un ciclo annidato in C?

Un singolo break esce solo dal ciclo più interno. Per uscire da entrambi puoi impostare un flag e verificarlo nella condizione del ciclo esterno, usare goto per saltare a un'etichetta dopo i cicli oppure, di solito la soluzione più pulita, spostare i cicli in una funzione e usare return.

break esce dal ciclo o solo dallo switch?

Da quello che lo racchiude più da vicino. Un break dentro uno switch che si trova in un ciclo termina solo lo switch; il ciclo prosegue. Per uscire dal ciclo dall'interno di uno switch serve un flag, un goto o un return.

Perché continue causa un ciclo infinito nel mio while?

Perché continue salta alla condizione e ignora il resto del corpo, compreso l'incremento del contatore se si trova alla fine. In un ciclo for l'aggiornamento sta nell'intestazione e quindi viene sempre eseguito; in un ciclo while sposta l'aggiornamento prima del continue oppure usa un for.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA