例如:
#define FOO(x) (printf(x))
和
#define FOO(x) {printf(x)}
似乎两者都可以进行预处理,但哪个更好?
答案 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))
如果优先级不是问题,则不一定要求括号类型,但根据宏语义可能需要大括号 - 例如,如果要创建局部变量,