宏中“do {...} while(0)”和“{...}((void)0)”之间的实际差异?

时间:2015-02-28 03:09:00

标签: c syntax macros

C中的常见做法是:

#define FOO() do { /* body */ } while (0)

虽然这很好,但也可以这样做:

#define FOO() { /* body */ }((void)0)

{...}((void)0)有许多相同的好处:你不能意外地合并逻辑,并且在行的末尾需要;,所以像这样的奇怪表达式不会通过un注意:FOO() else {...}

我注意到唯一的区别是它意味着你需要在if语句中使用大括号。

if (a)
    FOO();
else
    BAR();

必须写成:

if (a) {
    FOO();
} else {
    BAR();
}

除了这个怪癖之外,它似乎运作良好,可以防止同样的问题do/while方法通常用于。

两种方法之间是否存在显着差异?

不同地说,如果您看到使用{...}((void)0)的代码库,那么切换到使用do{..}while(0)的实际原因是什么,除了已经注意到的一个差异?

2 个答案:

答案 0 :(得分:7)

实际差异正如你所指出的那样。

do { ... } while (0)成语意味着宏可以在需要声明的任何上下文中使用。

您建议的成语{ ... } ((void)0)可以安全地用于需要表达式的大多数上下文中 - 但如果它在无支撑if中使用,则可能会失败言。

我认为没有充分的理由使用几乎总是有效的不熟悉的习语,当总是工作时,这是一个众所周知的习语。

答案 1 :(得分:2)

一个区别是您可以使用#define FOO() do { /* body */ } while (0)中断,但不能使用#define FOO() { /* body */ }(void)0

假设你在一个函数内部,比如hello(),并在#define FOO() do { /*some device operation */ } while (0)中做了一些事情,但发生了一些错误,所以你不再想继续使用该设备,但函数{{}中还有其他语句1}}你想要执行,让我们说另一个设备。

因此,如果您使用第二个语句,那么您将返回最可能退出hello()的语句,但如果您使用第一个语句,则可以愉快地hello()并在同一个函数中执行某些操作{{ 1}}用于其他设备。