C 多行宏:do/while(0) vs scope 块 [英] C multi-line macro: do/while(0) vs scope block

查看:10
本文介绍了C 多行宏:do/while(0) vs scope 块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

<块引用>

可能的重复:
do while(0) 当我们定义一个宏?
为什么有时会有C/C++ 宏中的 do/while 和 if/else 语句毫无意义?
做{ …} while (0) 有什么用?

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

<上一页>#define FOO 做 { do_stuff_here 做更多的东西} 而 (0)

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

<上一页>#define FOO { do_stuff_here 做更多的东西}

解决方案

Andrey Tarasevich 给出如下解释:

  1. 在 Google 网上论坛
  2. 在 bytes.com

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

<块引用>

使用do/while"版本的整个想法是制作一个宏,它将扩展为常规语句,而不是复合语句.这是这样做是为了使函数式宏的使用与在所有上下文中使用普通函数.

考虑以下代码草图:

if (<条件>)富(一);别的酒吧(一);

其中 foobar 是普通函数.现在想象你会喜欢将函数 foo 替换为上述性质的宏 [named CALL_FUNCS]:

if (<条件>)CALL_FUNCS(a);别的酒吧(一);

现在,如果您的宏是按照第二种方法定义的(只是 {})代码将不再编译,因为 'true'if 的分支现在由复合语句表示.当你在这个复合语句之后放一个 ;,你完成了整个 if语句,从而孤立 else 分支(因此编译错误).

纠正这个问题的一种方法是记住不要把 ; 放在后面宏调用":

if (<条件>)CALL_FUNCS(a)别的酒吧(一);

这将按预期编译和工作,但这并不统一.这更优雅的解决方案是确保宏扩展为常规声明,不成复合词.实现这一目标的一种方法是定义宏如下:

#define CALL_FUNCS(x) 做 { 函数1(x);函数2(x);函数3(x);} 而 (0)

现在这段代码:

if (<条件>)CALL_FUNCS(a);别的酒吧(一);

将编译没有任何问题.

但是,请注意我的定义之间的微小但重要的区别CALL_FUNCS 和您消息中的第一个版本.我没有放一个;} while (0) 之后.在该定义的末尾放置一个 ;会立即破坏使用do/while"的全部意义,并使该宏几乎等同于复合语句版本.

我不知道为什么你在原文中引用的代码的作者消息将此 ; 放在 while (0) 之后.在这种形式下,两种变体都是相等的.使用do/while"版本背后的整个想法不是将这个最后的 ; 包含到宏中(出于我解释的原因以上).

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?

I've seen some multi-line C macros that are wrapped inside a do/while(0) loop like:

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

What are the benefits (if any) of writing the code that way as opposed to using a basic block:

#define FOO 
  { 
    do_stuff_here 
    do_more_stuff 
  }

解决方案

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 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 块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆