【问题标题】:c++ macro sideeffectC++ 宏副作用
【发布时间】:2012-03-24 23:55:12
【问题描述】:

我不明白为什么结果会是 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;
}

非常感谢:>

【问题讨论】:

    标签: c++ macros side-effects


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 我的意思是你的答案 Seth,但奇怪的是 Stackoverflow 告诉我是 Oli 错误地发布了它。现在你的名字在它下面.. :/
      【解决方案3】:

      这一行:

      double result = QUADRAT(++no);
      

      扩展为:

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

      这最终运行的方式等价于:

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

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

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

      大多数现代编译器会在不进行文本替换的情况下扩展此代码 - 它们会为您提供与预处理器定义一样快的东西,但不会有遇到您面临的问题的危险。

      【讨论】:

        【解决方案4】:

        发生的是一种用 ++no 代替 x 的文字替换,就像你写的那样:

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

        结果是什么……应该是未定义的行为(你偶然得到 36),而带有 -Wall 的 g++ 同意我的看法。

        【讨论】:

          猜你喜欢
          • 2012-10-16
          • 1970-01-01
          • 1970-01-01
          • 2023-03-24
          • 1970-01-01
          • 2021-11-16
          • 1970-01-01
          • 2011-09-17
          • 1970-01-01
          相关资源
          最近更新 更多