Diverse spiegazioni. Il primo è generale, il secondo è specifico per le macro del preprocessore C con parametri:
Controllo del flusso
L'ho visto usato nel semplice codice C. Fondamentalmente, è una versione più sicura di goto, poiché puoi uscirne e tutta la memoria viene ripulita correttamente.
Perché qualcosa di gotosimile dovrebbe essere buono? Bene, se hai un codice in cui praticamente ogni riga può restituire un errore, ma devi reagire a tutti allo stesso modo (ad esempio consegnando l'errore al chiamante dopo la pulizia), di solito è più leggibile evitare un if( error ) { /* cleanup and error string generation and return here */ }as evita la duplicazione del codice di pulizia.
Tuttavia, in C ++ hai eccezioni + RAII esattamente per questo scopo, quindi lo considererei un cattivo stile di codifica.
Controllo punto e virgola
Se dimentichi il punto e virgola dopo un'invocazione di una macro simile a una funzione, gli argomenti potrebbero contrarsi in modo indesiderato e compilarsi in una sintassi valida. Immagina la macro
#define PRINT_IF_DEBUGMODE_ON(msg) if( gDebugModeOn ) printf("foo");
Questo viene accidentalmente chiamato come
if( foo )
PRINT_IF_DEBUGMODE_ON("Hullo\n")
else
doSomethingElse();
L '"altro" sarà considerato associato a gDebugModeOn, quindi quando fooè false, accadrà l'esatto contrario di ciò che era previsto.
Fornire un ambito per le variabili temporanee.
Poiché il do / while ha le parentesi graffe, le variabili temporanee hanno un ambito chiaramente definito da cui non possono sfuggire.
Evitare gli avvisi di "punto e virgola eventualmente indesiderato"
Alcune macro vengono attivate solo nelle build di debug. Li definisci come:
#if DEBUG
#define DBG_PRINT_NUM(n) printf("%d\n",n);
#else
#define DBG_PRINT_NUM(n)
#endif
Ora, se lo usi in una build di rilascio all'interno di un condizionale, si compila in
if( foo )
;
Molti compilatori lo vedono come lo stesso di
if( foo );
Che è spesso scritto accidentalmente. Quindi ricevi un avviso. Il do {} while (false) lo nasconde al compilatore e viene accettato da esso come un'indicazione che non si vuole fare nulla qui.
Evitare l'acquisizione di linee da condizionali
Macro dell'esempio precedente:
if( foo )
DBG_PRINT_NUM(42)
doSomething();
Ora, in una build di debug, poiché abitualmente includiamo anche il punto e virgola, viene compilato perfettamente. Tuttavia, nella build di rilascio questo si trasforma improvvisamente in:
if( foo )
doSomething();
O più chiaramente formattato
if( foo )
doSomething();
Che non è affatto ciò che era previsto. L'aggiunta di un do {...} while (false) attorno alla macro trasforma il punto e virgola mancante in un errore di compilazione.
Cosa significa per l'OP?
In generale, si desidera utilizzare le eccezioni in C ++ per la gestione degli errori e i modelli invece delle macro. Tuttavia, nel caso molto raro in cui hai ancora bisogno di macro (ad es. Quando si generano nomi di classi usando il token paste) o sono limitati al semplice C, questo è un modello utile.