c ++宏观副作用

时间:2012-03-24 23:55:13

标签: c++ macros side-effects

我不明白为什么结果会是36.有人可以向我解释这里发生了什么以及预处理器的作用是什么?

#include <iostream>
#define QUADRAT(x) ((x) * (x))

using namespace std;

int main()
{
    double no = 4.0;
    double result = QUADRAT(++no);

    cout << result;
    return 0;
}

非常感谢:&gt;

4 个答案:

答案 0 :(得分:4)

在该示例中,预处理器将QUADRAT(++no)替换为((++no) * (++no))

如果不是因为两个增量之间没有序列点,那么会增加no两次,所以实际上是在引起未定义的行为。您看到的任何输出都是有效的,因为没人知道会发生什么。

答案 1 :(得分:2)

预处理器基本上是一个复制粘贴引擎。请注意,宏是一个函数;相反,它是内联扩展的。考虑扩展宏时代码会发生什么。

答案 2 :(得分:1)

这一行:

double result = QUADRAT(++no);

扩展到这个:

double result = ((++no) * (++no));

最终运行的方式相当于:

no = no + 1;
no = no + 1;
result = no * no;

它以这种方式运行,因为增量是在乘法之前执行的:预处理器会对你传递的内容进行文本复制,因此它会复制“++ no”,使其在最终代码中显示两次,并且在计算结果之前,没有发生每个++的增量。解决这个问题的方法是使用内联函数:

inline double QUADRAT(double x) { return x * x; }

大多数现代编译器都会在不进行文本替换的情况下扩展此代码 - 它们会为您提供与预处理器定义一样快的速度,但不会出现像您所面临的那样的问题。

答案 3 :(得分:0)

会发生什么事情是用+代替x的字面替换,就像你写的那样:

double result = ((++no) * (++no));

结果是什么......它应该是未定义的行为(你偶然得到36),并且带有-Wall的g ++与我同意。