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

从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一样Streq

 #include  #include  #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 

你能想象使用这些宏吗? MyStreq会做出人们期望的但是MyStreq没有?

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

 #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. } 

括号确实有时很重要,无条件插入它们是个好主意。 考虑以下可怜的宏:

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

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

如果你在每个参数的使用周围读到带有括号的宏定义,那么作者肯定会记住这个问题 – 即使那些parens恰好是该宏的冗余。