宏的问题

时间:2009-08-29 10:15:13

标签: c++ macros vc6

HI,

有人可以帮助我理解为什么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;
}

4 个答案:

答案 0 :(得分:16)

Neil Butterworth,Mark和Pavel是对的。

SQUARE(++ y)扩展为++ y * ++ y,它的增量是y的两倍。

您可能遇到的另一个问题:SQUARE(a + b)扩展为a + b * a + b,它不是(a + b)*(a + b)而是a +(b * a)+ b。在定义宏时,您应该在需要时在元素周围添加括号:#define SQUARE(X)((X)*(X))风险稍低。 (Ian Kemp在他的评论中首先写了它)

您可以改为使用内联模板函数(在运行时效率不低),如下所示:

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)

答案 1 :(得分:15)

因为宏扩展为:

++y * ++y

在C ++中给出了未定义的行为 - 结果可以 做任何事。任何涵盖宏使用的体面教科书都应该涵盖这个众所周知的问题。你在用哪一个?

答案 2 :(得分:5)

因为宏会进行文本替换,所以您编写的代码会扩展为

printf("%d\n",++y * ++y );

然后操作的顺序是未定义的行为,因此编译器看到2个增量,然后是乘法

因此,最好小心使用宏,因为编译器可以内联扩展不再需要运行。

其次不要假设如果增加和使用变量会发生什么

答案 3 :(得分:5)

宏不是函数:它们只是改变程序的文本。此操作称为预处理,它在代码编译之前自动执行。人们编写宏来节省时间并为源代码引入一些可变性。

当您编写SQUARE(x)时,不会发生实际的函数调用,只会修改文本。操作非常愚蠢,所以你必须在像你这样的情况下采取额外的预防措施。请参阅其他答案以解释您的案例。