2012-12-07 19 views
6

Eventuali duplicati:
Do-While and if-else statements in C/C++ macrosfunzione come macro parentesi graffe o do..while

gcc (GCC) 4.7.2 
c89 

Ciao,

ho la seguente funzione simil-macro e basta chiedendosi qual è l'utilizzo preferito quando si utilizza su più linee. È meglio usare le parentesi graffe o il ciclo do..while (0).

Normalmente utilizzo un do..while (0) per tutto. Ma ho visto alcuni progetti in cui usano solo le parentesi graffe e non sono sicuro di quale sia la migliore.

do..while

#define DSO_ERROR(msg, res_handle_module, mem_pool, size) do {  \ 
     char *dso_error = apr_palloc((apr_pool_t*)mem_pool, size);  \ 
     apr_dso_error((apr_dso_handle_t*)res_handle_module, (char*)dso_error, (apr_size_t)size); \ 
     LOG_ERR("%s dso error %s", (char*)msg, dso_error);    \ 
     goto dso_failure;            \ 
    } while(0); 

graffe

#define DSO_ERROR(msg, res_handle_module, mem_pool, size) {    \ 
     char *dso_error = apr_palloc((apr_pool_t*)mem_pool, size);  \ 
     apr_dso_error((apr_dso_handle_t*)res_handle_module, (char*)dso_error, (apr_size_t)size); \ 
     LOG_ERR("%s dso error %s", (char*)msg, dso_error);    \ 
     goto dso_failure;            \ 
    } 

L'unica differenza è che un semi-colon sarà preimpostato sul ciclo do..while e non sulle parentesi graffe.

Molte grazie per qualsiasi suggerimento,

+1

Mio Dio, questo è un brutto codice. (senza offesa intesa, sono solo molto sorpreso). – rubenvb

+3

L'aggiunta del punto e virgola alla fine di 'do {...} while (0)' impedisce lo scopo di usare 'do {...} while (0)' in primo luogo. Lo svantaggio della versione solo per bretelle è che non puoi scrivere 'if (qualcosa) DSO_ERROR (...); else {...} 'perché il punto e virgola è un'istruzione null dopo' if' e 'else' è un errore di sintassi. Con la versione corretta di 'do {...} while (0)', la notazione 'if' /' else' funziona come ci si aspetterebbe se la macro fosse effettivamente una funzione. –

risposta

7

La versione parentesi graffa si romperà l'utilizzo in questo modo:

if(foo) 
    DSO_ERROR("Foo occured!", my_module, the_pool, 4711); 
else 
    printf("All is well, there is no foo\n"); 

che è la ragione per la do ... while(0) costrutto. Quindi sembra che valga la pena di evitarlo.

+2

Come scritto da OP, anche la versione do ... while (0) si interrompe perché alla fine ha un punto e virgola in più. Il modo giusto per scrivere il do ... while (0) è senza punto e virgola. –

2

Di solito si fa non hanno il punto e virgola sul do { ... } while (0) nella macro.

La ragione per cui si dispone di do { ... } while (0) per la macro è che quindi è possibile utilizzare la macro nell'origine e aggiungere un punto e virgola senza che vi sia un'istruzione extra vuota. Questo è principalmente per ragioni storiche, suppongo, dato che avere dichiarazioni vuote (cioè solo punto e virgola senza alcuna istruzione) non fa nulla in molti casi.

+5

"... non fa nulla" eccetto il problema dell'alternativo pendente –

4

si avrà un problema con questo codice:

if (one) 
    DSO_ERROR("one", ...); 
else 
    DSO_ERROR("two", ...); 

quindi se si utilizza il do-while-Macro SENZA il punto e virgola, si andrebbe bene.