Why use do { } while (0) in macro definition?

18,558

Solution 1

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

If function1() is actually a macro, just using { } requires you to omit the semicolon at the point of use, but do { } while(0) lets you use exactly the same syntax as for a real function.

(Not using any kind of block construct at all would just generate completely broken code, natch)

Solution 2

Enclosing code with a loop allows for a preprocessor directive to execute multiple statements without "breaking" if-else-constructs. Consider the following:

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

The second example breaks the if-else-construct because three statements are followed by an else clause. To allow for it to correctly substitute, the instructions in DO_SOMETHING should be enclosed with a do { ... } while(0).

Solution 3

A do{}while(0) allows you to break from the loop:

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

It's the same as a simple block {...} except that you can break execution when you want with the break statement. You couldn't do that in a simple code block, unless you have multiple checks, which can get cumbersome. It still gets executed once, because of the condition while(0).

Share:
18,558
ciphor
Author by

ciphor

I'm a programmer.

Updated on June 12, 2022

Comments

  • ciphor
    ciphor about 2 years

    Possible Duplicate:
    Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?

    I met code like below:

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

    I want to know why the author use do { } while (0) here. Is there any difference with this?

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

    BTW: the code is from libev, ev_local.h

  • moonshadow
    moonshadow over 12 years
    ...it does, but please don't...
  • Simon
    Simon over 12 years
    of course, if you use naked if lines like that, you deserve for your code to break...
  • CoderSpinoza
    CoderSpinoza over 8 years
    @Simon But doesn't linux kernel coding style advice us to use naked if else lines for one line block? kernel.org/doc/Documentation/CodingStyle
  • Simon
    Simon over 8 years
    @CoderSpinoza apparently so, and if I were to work on the linux kernel then I would follow that style. Elsewhere, I'd avoid it.
  • Elvis Teixeira
    Elvis Teixeira over 6 years
    A lot of C code repos use one line ifs without braces, and it is totally fine.
  • KRoy
    KRoy over 6 years
    It reduces the number of if-else nesting.