我们可以删除C宏定义中参数周围的括号吗?
从http://c-faq.com/style/strcmp.html ,我学到了以下便利宏:
#define Streq(s1, s2) (strcmp((s1), (s2)) == 0)
我想知道为什么在这个宏中使用了这么多括号。 每个括号是用于某个目的还是使用冗余括号的宏,这些括号没有用处?
我们可以删除s1
和s2
周围的括号并制作这样的宏吗?
#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恰好是该宏的冗余。