2012-02-29 15 views
13

Duplicar posible:
Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?¿Por qué usar do {} while (0) en la definición de macro?

me encontré con un código como a continuación:

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

Quiero saber por qué el autor utiliza do { } while (0) aquí. ¿Hay alguna diferencia con esto?

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

Por cierto: el código es de libev, ev_local.h

Respuesta

10

Un do{}while(0) le permite romper el bucle de:

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

Es lo mismo que un simple bloque {...} excepto que se puede interrumpir la ejecución cuando lo desee con la instrucción break. No podrías hacer eso en un simple bloque de código, a menos que tengas múltiples controles, que pueden ser engorrosos. Todavía se ejecuta una vez, debido a la condición while(0).

+8

... lo hace, pero por favor no ... – moonshadow

+0

Se reduce el número de anidación if-else . – shuva

15

código Encerrar con un bucle permite una directiva de preprocesador para ejecutar varias instrucciones sin "romper" if-else-construcciones. Considere lo siguiente:

#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(); 
} 

El segundo ejemplo rompe el if-else-construir porque tres declaraciones son seguidas por una cláusula else. Para permitir que se sustituya correctamente, las instrucciones en DO_SOMETHING deben adjuntarse con un do { ... } while(0).

+3

por supuesto, si se utiliza desnudo si las líneas de ese tipo, que merecen por su código de romper ... – Simon

+2

@Simon Pero no del núcleo de Linux consejos de estilo de codificación nos utilizar desnudo si las líneas de otros accesorios para bloquear una línea? https://www.kernel.org/doc/Documentation/CodingStyle – CoderSpinoza

+2

@CoderSpinoza aparentemente es así, y si tuviera que trabajar en el núcleo de Linux entonces se seguiría que estilo. En otro lugar, lo evitaría. – Simon

23

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

Si function1() es en realidad una macro, simplemente usando { } requiere omitir el punto y coma en el punto de uso, pero do { } while(0) le permite utilizar exactamente la misma sintaxis que para una función real.

(sin utilizar ningún tipo de construcción de bloques en absoluto que acaba de generar código completamente roto, naturalmente)