我们可以删除 C 宏定义中参数周围的括号吗?

Posted

技术标签:

【中文标题】我们可以删除 C 宏定义中参数周围的括号吗?【英文标题】:Can we remove parentheses around arguments in C macros definitions? 【发布时间】:2015-03-01 09:19:36 【问题描述】:

从http://c-faq.com/style/strcmp.html,我学到了以下便利宏:

#define Streq(s1, s2) (strcmp((s1), (s2)) == 0)

我想知道为什么在这个宏中使用了这么多括号。每个括号是有目的的,还是这个宏使用了没有目的的多余括号?

我们可以去掉s1s2 周围的括号,然后做一个这样的宏吗?

#define MyStreq(s1, s2) (strcmp(s1, s2) == 0)

MyStreq 宏对我来说似乎和Streq 一样好用。

#include <string.h>
#include <stdio.h>

#define Streq(s1, s2) (strcmp((s1), (s2)) == 0)
#define MyStreq(s1, s2) (strcmp(s1, s2) == 0)

int main()

    printf("%d %d\n", Streq("foo", "foo"), MyStreq("foo", "foo"));
    printf("%d %d\n", Streq("fox", "foo"), MyStreq("fox", "foo"));
    printf("%d %d\n", Streq("foo", "fox"), MyStreq("foo", "fox"));
    return 0;

以上代码的输出:

1 1
0 0
0 0

您能想象这些宏的任何用法,其中Streq 会执行预期的操作,而MyStreq 不会?

【问题讨论】:

相关:The need for parentheses in macros in C 相关:When can the parentheses around arguments in macros be omitted? 【参考方案1】:

这是一个相对愚蠢的例子,但它确实有不同的结果:

#define Streq(s1, s2) (strcmp((s1), (s2)) == 0)
#define MyStreq(s1, s2) (strcmp(s1, s2) == 0)
#define s1 "foo", "blah"

int main() 
    Streq(s1, "blah"); // Compiles and compares equal.
    MyStreq(s1, "blah"); // Compiler error. Too many parameters.

【讨论】:

【参考方案2】:

括号有时很重要,无条件插入括号是个好主意。考虑以下糟糕的宏:

#define OP(a, b) (a * b) /* BAD */

OP(x + 1, y + 1) 调用,它将扩展为 x + 1 * y + 1,从而破坏了预期的分组。括号可以防止这个问题。

如果您阅读的宏定义在每个参数使用时都带有括号,那么作者肯定会想到这个问题 - 即使这些括号恰好对于该宏来说是多余的。

【讨论】:

以上是关于我们可以删除 C 宏定义中参数周围的括号吗?的主要内容,如果未能解决你的问题,请参考以下文章

c语言宏定义有无参数的区别

C语言问题,宏定义中的参数为啥要定义,不是主函数中的参数直接替换吗?

C/C++宏定义可不可以传入参数?

C语言带参数的宏定义:定义宏名时可以不写出参数???

C语言宏定义实现可变参数

C语言中的宏定义怎么用?