在定义宏时,您基本上总是希望将宏参数放在括号中以防止在第一个示例中出现那种奇怪的行为,并将结果放在括号中,以便可以安全地使用它而不会产生副作用。使用
#define SQR(x) ((x)*(x))
使得SQR(a+b)展开到((a+b)*(a+b))在数学上是正确的(不像a+b*a+b,它等于 ab+a+b)。
在宏之前或之后放置东西不会进入宏。++SQR(x)在您的++x*x示例中也是如此。
请注意以下事项:
int a=3, b=1;
SQR(a+b) // ==> a+b*a+b = 3+1*3+1 = 7
++SQR(a+b) // ==> ++a+b*a+b ==> 4 + 1*4 + 1 = 9
// since preincrement will affect the value of a before it is read.
您会看到++SQR(a+b)似乎增加了 2,因为在a我读取任一时间之前预增量开始,即a递增,然后使用两次,因此结果比预期的高 2。
注意正如@JonathanLeffler 指出的那样,后一个调用会调用未定义的行为;评估不保证从左到右进行。它可能会在不同的编译器/操作系统上产生不同的结果,因此永远不应依赖它。