在C中定义类似函数的宏时,使用{}对或()对有什么区别吗?

时间:2010-04-26 09:08:56

标签: c c-preprocessor

例如:

#define FOO(x)     (printf(x))

#define FOO(x)     {printf(x)}

似乎两者都可以进行预处理,但哪个更好?

4 个答案:

答案 0 :(得分:6)

如果您将宏视为表达式,请使用()表单。

如果您将其视为命令(从不作为表达式),请使用{}表单。或者更确切地说,使用do{}while(0)表单,因为在if等关键字附近使用时,替换风险较小:

#define FOO(x) do {    \
    printf(x);         \
} while(0)

答案 1 :(得分:2)

括号()用于强制执行正确的评估,无论运算符优先级如何,因此在扩展宏时,您希望不会产生任何令人讨厌的副作用。

大括号{}用于使宏成为C块语句,尽管执行此操作的规范方法是:

#define FOO(x) \
  do { \
    ... stuff ... \
  } while (0)

请注意,gcc提供了C语言的扩展,这使得可以从块返回一个值 - 如果块被用作表达式的一部分,则最后一个表达式将是返回的值。

答案 2 :(得分:1)

如果您在表达式中需要FOO(x),则无法使用{}表单。例如:

result = FOO(some_variable);

if (FOO(some_variable))

答案 3 :(得分:1)

在宏中使用parens的目的是在扩展宏时控制优先级。考虑:

#define X( a, b ) a * b

如果像这样使用宏

X( 1 + 2, 3 )

我们可能会觉得答案是9,但我们得到的扩展是:

1 + 2 * 3

给我们7.为了避免这种情况,我们应该把宏写成:

#define X( a, b ) ((a) * (b))

如果优先级不是问题,则不一定要求括号类型,但根据宏语义可能需要大括号 - 例如,如果要创建局部变量,