通常我常常觉得宏定义中围绕参数的一些括号是多余的。将所有内容括起来太不方便了。如果我可以保证参数不需要括号,我可以省略括号吗?或者强烈建议将它们括起来?
我在写作时提出了这个问题:
#define SWAP_REAL(a, b, temp) do{double temp = a; a = b; b= temp;}while(0)
我认为如果参数在宏中显示为l值,则可以省略括号,因为这意味着参数出现时没有其他操作。
我的理由是:
您不能混淆编译器,认为您的参数是一个带逗号的表达式。例如,SWAP(a, b, b)
将无法成功解释为
do{double temp = a, b; a, b = b; b= temp;}while(0)
可以通过编译。
我是对的吗?任何人都可以给我一个反例吗?
在以下示例中,
#define ADD(a, b) (a += (b))
我认为论证a
不需要用括号括起来。在这种特殊情况下,既不需要参数b
,也不需要?
@JaredPar:
#include <stdio.h> #define ADD(a, b) (a += (b)) int main(){ int a = 0, b = 1; ADD(a; b, 2); return 0; }
这在我的VS2010上无法成功编译。 Error C2143: syntax error : missing ')' before ';'
简而言之,您不需要将在宏中显示为l值的参数括起来,但强烈建议您将它们全部括起来。
宏规则:
答案 0 :(得分:3)
这是一个可以产生明显差异的案例
ADD(x;y, 42)
使用parens会导致编译错误,但如果没有它会导致编译代码。
(x;y) += 42; // With parens errors
x;y += 42; // Without parens compiles
这可能看起来像一个愚蠢的例子,但可能将宏组合在一起很容易导致奇怪的代码表达式,如上所述。
为什么要冒这个机会?这只是2个字符
答案 1 :(得分:2)
如果在表达式中使用任何不是最低优先级的运算符,则省略它是不安全的。我相信这将是逗号。
a op b
其中op
是某些运算符,如+
,*
等,如果a
包含低优先级的表达式,例如{{1 || 2
将始终绑定错误1}}。
注意我不声称在这些情况下它是安全的。有更多创造性的方法来打破宏。顺便说一句,首先不要使用带副作用的宏。更一般地说,不要使用宏作为函数。 (参见,例如,Effective C ++)。
答案 2 :(得分:0)
有些宏用于连接元素以生成字符串(可能使用#
运算符),或使用##
运算符从宏参数构建标识符。在这种情况下,您不会将参数括起来。
另外,我认为当宏参数本身作为函数参数传递时,你不必绝对将它们括起来:
#define CALLOC(s, n) calloc(s, n)
你可以玩恶魔游戏调用这样一个宏(CALLOC({3, 4})
),但你得到你应得的(编译错误) - 我不知道一种调用那个宏的方法,如果不是您编写与calloc()
直接调用相同的参数的宏。
但是,如果您在大多数算术表达式中使用参数,那么您需要将它们包装在括号中:
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
显然,如果你用带副作用的参数调用它,那么你得到的就是你得到的。但这些论点不会被误解,因为如果你写的话可能会这样:
#define MIN(x, y) x < y ? x : y
然后将其调用为:
MIN(x = 3 * y + 1, y = 2 * x - 2);
以下使用该宏的代码在使用默认选项进行编译时干净地编译,但无法使用-DWITH_PARENTHESES
set进行编译。
#include <stdio.h>
#ifdef WITH_PARENTHESES
#define SWAP_INT(a, b) do { int temp = (a); (a) = (b); (b) = temp; } while (0)
#else
#define SWAP_INT(a, b) do { int temp = a; a = b; b = temp; } while (0)
#endif
int main(void)
{
int p = 319;
int q = 9923;
int x = 23;
int y = 300;
printf("p = %8d, q = %8d, x = %8d, y = %8d\n", p, q, x, y);
SWAP_INT(p, q); // OK both ways
SWAP_INT(x, y); // OK both ways
printf("p = %8d, q = %8d, x = %8d, y = %8d\n", p, q, x, y);
SWAP_INT(x /= y, p *= q); // Compiles without parentheses; fails with them
printf("p = %8d, q = %8d, x = %8d, y = %8d\n", p, q, x, y);
return 0;
}
输出:
p = 319, q = 9923, x = 23, y = 300
p = 9923, q = 319, x = 300, y = 23
p = 41150681, q = 13, x = 0, y = 3165437
这不是交换整数的安全或有效方式 - 没有括号的宏不是一个好主意。