2012-02-29 8 views
13

Eventuali duplicati:
Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?Perché utilizzare do {} while (0) nella definizione macro?

ho incontrato il codice come di seguito:

#define ev_io_init(ev,cb,fd,events) \ 
do { \ 
    ev_init ((ev), (cb)); \ 
    ev_io_set ((ev),(fd),(events)); \ 
} while (0) 

voglio sapere perché l'autore usa do { } while (0) qui. C'è qualche differenza con questo?

#define ev_io_init(ev,cb,fd,events) { \ 
    ev_init ((ev), (cb)); \ 
    ev_io_set ((ev),(fd),(events)); \ 
} 

BTW: il codice è da libev, ev_local.h

risposta

10

Un do{}while(0) permette di rompere dal loop:

do{ 
    expr1; 
    foo(); 
    if (cond) 
     break; 
    expr2; 
    goo(); 
} while (0); 

E 'lo stesso come un semplice blocco {...} tranne che si può interrompere l'esecuzione quando si desidera con l'istruzione break. Non è possibile farlo in un semplice blocco di codice, a meno che non si disponga di più assegni, che possono essere ingombranti. Viene ancora eseguito una volta, a causa della condizione while(0).

+8

... che fa, ma per favore non ... – moonshadow

+0

Si riduce il numero di if-else la nidificazione . – shuva

15

Racchiudere il codice con un ciclo consente a una direttiva del preprocessore di eseguire più istruzioni senza "interrompere" if-else-construct. Considerare quanto segue:

#define DO_SOMETHING() a();b();c(); 

void foo() 
{ 
    // This is ok... 
    DO_SOMETHING(); 
} 

void bar() 
{ 
    // ...whereas this would trigger an error. 
    if (condition) 
     DO_SOMETHING(); 
    else 
     blah(); 
} 

Il secondo esempio rompe if-else-costrutto perché tre affermazioni sono seguite da una clausola else. Per consentirne una corretta sostituzione, le istruzioni in DO_SOMETHING devono essere allegate a do { ... } while(0).

+3

ovviamente, se usi nude se linee del genere, ti meriti la rottura del tuo codice ... – Simon

+2

@Simon Ma lo stile di codifica del kernel di Linux non ci consiglia di usare nudi se no le linee per un blocco di linea? https://www.kernel.org/doc/Documentation/CodingStyle – CoderSpinoza

+2

@CoderSpinoza a quanto pare, e se dovessi lavorare sul kernel Linux, seguirò quello stile. Altrove, lo eviterei. – Simon

23

consideri if(something) function1(); else function2();

Se function1() è in realtà una macro, usando solo { } richiede di omettere il punto e virgola al punto di utilizzo, ma do { } while(0) consente di utilizzare esattamente la stessa sintassi di una funzione reale.

(non utilizzando qualsiasi tipo di blocco costrutto a tutti sarebbe solo generare il codice completamente rotto, natch)