嗨,宏问题
有人能帮我理解为什么SQUARE(x)的值是49吗?
我正在使用Visual C++ 6.0。
#define SQUARE(X) X * X
int main(int argc, char* argv[])
{
int y = 5;
printf("%d\n",SQUARE(++y));
return 0;
}
嗨,宏问题
有人能帮我理解为什么SQUARE(x)的值是49吗?
我正在使用Visual C++ 6.0。
#define SQUARE(X) X * X
int main(int argc, char* argv[])
{
int y = 5;
printf("%d\n",SQUARE(++y));
return 0;
}
尼尔巴特沃斯,马克和帕维尔是正确的。
SQUARE(++ y)扩展为++ y * ++ y,它将y的值增加两倍。 (a + b)不是(a + b)*(a + b),而是a +(b * a)+ b扩展到a + b * a + b。在定义宏时,您应该注意在需要时在元素周围添加括号:#define SQUARE(X)((X)*(X))风险较小。 (伊恩·肯普在他的评论中第一次写的)
你也可以使用内联模板函数(没有在运行时效率较低),像这样的:
template <class T>
inline T square(T value)
{
return value*value;
}
您可以检查它的工作原理:
int i = 2;
std::cout << square(++i) << " should be 9" << std::endl;
std::cout << square(++i) << " should be 16" << std::endl;
(没有必要写
square<int>(++i)
因为int类型是隐含的对于i)
因为宏展开:
++y * ++y
,其给出了C++未定义行为 - 其结果可能 是任何东西。这个众所周知的问题应该涵盖任何涵盖宏使用的正派教科书。你在使用哪一个?
你也可以看到6x7 = 42,这取决于你的编译器。 – 2009-08-29 10:21:24
@愿意 - 或者你可能没有得到42. – 2009-08-29 21:26:48
因为宏做文本替换,所以你写的代码被扩大到
printf("%d\n",++y * ++y);
,然后操作的顺序是不确定的行为,使这个编译器看到2个增量,然后乘
所以要谨慎使用宏,以便使用函数,因为编译器可以扩展内联,不再需要运行。
其次不要以为你增加会发生什么,并使用变量
宏不是函数:他们只是改变了程序的文本。该操作被称为预处理,并且在编译代码之前它会自动执行。人们编写宏以节省时间并在源代码中引入一些可变性。
当您编写SQUARE(x)
时,不会发生实际的功能调用,只是文本被修改。操作非常笨拙,所以你必须在像你这样的情况下采取额外的预防措施。请参阅其他答案以解释您的案例。
啊,这个老栗子......要得到你应该使用的正确结果:#define SQUARE(X)((X)*(X))。 – 2009-08-29 10:28:16
@我错了,恐怕。 – 2009-08-29 10:32:56
Ian Kemp的评论确实是错误的,因为它没有解决问题。但是,在宏中,更好的方法是添加括号:SQUARE(a + b)扩展为不是(a + b)*(a + b)的a + b * a + b,而是a +(b * a)+ b。 – moala 2009-08-29 11:02:18