C 多行宏 : do/while(0) vs scope block

标签 c macros multiline

<分区>

Possible Duplicates:
What’s the use of do while(0) when we define a macro?
Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?
do { … } while (0) what is it good for?

我见过一些包含在 do/while(0) 循环中的多行 C 宏,例如:

#define FOO \
  do { \
    do_stuff_here \
    do_more_stuff \
  } while (0)

与使用基本 block 相比,以这种方式编写代码有什么好处(如果有的话):

#define FOO \
  { \
    do_stuff_here \
    do_more_stuff \
  }

最佳答案

Andrey Tarasevich 提供了以下解释:

  1. On Google Groups
  2. On bytes.com

[对格式进行了细微更改。在方括号 []] 中添加括号注释。

The whole idea of using 'do/while' version is to make a macro which will expand into a regular statement, not into a compound statement. This is done in order to make the use of function-style macros uniform with the use 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'd like 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 you put a ; after this compound statement, you finished the whole if statement, thus orphaning the else branch (hence the compilation error).

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

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

This will compile and work as expected, but this is not uniform. The more elegant solution is to make sure that macro expand into a regular statement, not into a compound one. One way to achieve that is to define the 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 definition of CALL_FUNCS and the first version in your message. I didn't put a ; after } while (0). Putting a ; at the end of that definition would immediately defeat the entire point of using 'do/while' and make that macro pretty much equivalent to the compound-statement version.

I don't know why the author of the code you quoted in your original message put this ; after while (0). In this form both variants are equivalent. The whole idea behind using 'do/while' version is not to include this final ; into the macro (for the reasons that I explained above).

关于C 多行宏 : do/while(0) vs scope block,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42512191/

相关文章:

c - 预处理器中的地标和非地标标记?

hadoop - 在对多行数据集使用 Pig 时对相似值执行计数

c# - C# 中的 XML 多行注释 - 我做错了什么?

c - Windows RPC 编程错误 : LNK 2019 unresolved external symbol RPCServerListen

C - Linux 内核 - 协助 current_uid()

计算预处理器宏中的调用次数

c - 如果包含额外的头文件如何处理?

c - 如何读取 "int (*functionFactory(int n))(int, int) { ... }"?

javascript - JS : Can I call a function with same scope as caller or do macro-like behavior

PyCharm:使用键盘在当前插入符上方或下方添加插入符不起作用