C multi-line macro: do/while(0) vs scope block [duplicate] C multi-line macro: do/while(0) vs scope block [duplicate] c c

C multi-line macro: do/while(0) vs scope block [duplicate]


Andrey Tarasevich provides the following explanation:

  1. On Google Groups
  2. On bytes.com

[Minor changes to formatting made. Parenthetical annotations added in square brackets []].

The whole idea of using 'do/while' version is to make a macro which willexpand into a regular statement, not into a compound statement. This isdone in order to make the use of function-style macros uniform with theuse of ordinary functions in all contexts.

Consider the following code sketch:

if (<condition>)  foo(a);else  bar(a);

where foo and bar are ordinary functions. Now imagine that you'dlike to replace function foo with a macro of the above nature [named CALL_FUNCS]:

if (<condition>)  CALL_FUNCS(a);else  bar(a);

Now, if your macro is defined in accordance with the second approach(just { and }) the code will no longer compile, because the 'true'branch of if is now represented by a compound statement. And when youput a ; after this compound statement, you finished the whole ifstatement, thus orphaning the else branch (hence the compilation error).

One way to correct this problem is to remember not to put ; aftermacro "invocations":

if (<condition>)  CALL_FUNCS(a)else  bar(a);

This will compile and work as expected, but this is not uniform. Themore elegant solution is to make sure that macro expand into a regularstatement, not into a compound one. One way to achieve that is to definethe macro as follows:

#define CALL_FUNCS(x) \do { \  func1(x); \  func2(x); \  func3(x); \} while (0)

Now this code:

if (<condition>)  CALL_FUNCS(a);else  bar(a);

will compile without any problems.

However, note the small but important difference between my definitionof CALL_FUNCS and the first version in your message. I didn't put a; after } while (0). Putting a ; at the end of that definitionwould immediately defeat the entire point of using 'do/while' and makethat macro pretty much equivalent to the compound-statement version.

I don't know why the author of the code you quoted in your originalmessage put this ; after while (0). In this form both variants areequivalent. The whole idea behind using 'do/while' version is not toinclude this final ; into the macro (for the reasons that I explainedabove).