21

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

Community
  • 1
  • 1
ciphor
  • 8,018
  • 11
  • 53
  • 70

3 Answers3

32

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)

moonshadow
  • 86,889
  • 7
  • 82
  • 122
21

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).

Linus Kleen
  • 33,871
  • 11
  • 91
  • 99
  • 4
    of course, if you use naked if lines like that, you deserve for your code to break... – Simon Feb 29 '12 at 08:54
  • 2
    @Simon But doesn't linux kernel coding style advice us to use naked if else lines for one line block? https://www.kernel.org/doc/Documentation/CodingStyle – CoderSpinoza Nov 23 '15 at 03:17
  • 2
    @CoderSpinoza apparently so, and if I were to work on the linux kernel then I would follow that style. Elsewhere, I'd avoid it. – Simon Nov 23 '15 at 11:25
  • 2
    A lot of C code repos use one line ifs without braces, and it is totally fine. – Elvis Teixeira Jan 04 '18 at 19:37
13

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).

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625