Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 837
ciphor Avatar asked Feb 29 '12 08:02

ciphor


People also ask

Why do we use do while 0?

You may see a do loop with the conditional expression set to a constant value of zero (0). This creates a loop that will execute exactly one time. This is a coding idiom that allows a multi-line macro to be used anywhere that a single statement can be used.

Why do macros use do while?

In conclusion, macros in Linux and other codebases wrap their logic in do/while(0) because it ensures the macro always behaves the same, regardless of how semicolons and curly-brackets are used in the invoking code.

Why define while do?

The do while loop checks the condition at the end of the loop. This means that the statements inside the loop body will be executed at least once even if the condition is never true. The do while loop is an exit controlled loop, where even if the test condition is false, the loop body will be executed at least once.

What is __ Va_args __?

To use variadic macros, the ellipsis may be specified as the final formal argument in a macro definition, and the replacement identifier __VA_ARGS__ may be used in the definition to insert the extra arguments. __VA_ARGS__ is replaced by all of the arguments that match the ellipsis, including commas between them.


2 Answers

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)

like image 57
moonshadow Avatar answered Oct 18 '22 10:10

moonshadow


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

like image 43
Linus Kleen Avatar answered Oct 18 '22 10:10

Linus Kleen