前些天去参加一个笔试,其中有一个关于C++带参数的宏的题目,题目是这样的:
#define SQR(X) X*X
void main()
{
int a = 10;
int k = 2;
int m = 1;
a/=SQR(k+m)/SQR(k+m);
cout<< a<<endl;
} 要求写出结果。
当时我的解法是参数的简单替换a=a/k+m*k+m/k+m*k+m得到a的值为10,但后来在VC++上运行的结果是1。
我就想,难道是我对带参数宏的理解错误?在搜索引擎上搜索了很多相关的信息,发现搜索出来的一个错误解释能得出正确的结果,大量的转载让人把谎言误以为是真理,我也因此变得更加迷惑。网上转载的解释是:
在编译时,只是简单的代换X*X,
a /= (k+m)*(k+m)/(k+m)*(k+m)
=>a /= (k+m)*1*(k+m)
=>a = a/9
=>a = 1
但如果测试SQR(k+m)的值为5而非9,经过了几组数据的测试和查阅资料总结如下:
第一,带参数的宏定义的一般形式如下:#define <宏名>(<参数表> <宏体>,如果我们把宏定义时出现的参数视为形参,而在程序中引用宏定义时出现的参数视为实参,在宏替换时,就是用实参来替换<宏体>中的形参。SQR(k+m)/SQR(k+m)预编译后为 k+m*k+m/k+m*k+m。
第二,op= 形式的操作符(如 += , -= , *= , /= , %= , <<= , >>= , &= ^= , |= )为“符合赋值操作符”具有低优先级。
那么a/=SQR(k+m)/SQR(k+m)=>a /= k+m*k+m/k+m*k+m => a /= 7 =>a = a/7 =>a = 1; 得出正确的结果。