【问题标题】:Problem with Macros宏的问题
【发布时间】:2009-08-29 10:15:13
【问题描述】:

你好,

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

【问题讨论】:

  • 啊,这个老栗子...要获得正确的结果,您应该使用:#define SQUARE(X) ((X) * (X))。
  • @Ian 错了,我害怕。
  • Ian Kemp 的评论确实是错误的,因为它并没有解决问题。但是,最好在宏中添加括号: SQUARE(a + b) 扩展为 a + b * a + b 不是 (a+b)*(a+b) 而是 a + (b* a) + b.

标签: c++ macros visual-c++-6


【解决方案1】:

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) 是隐含的

【讨论】:

  • 你在哪里写“不需要写square(++i)”我想你的意思是“不需要写square&lt;int&gt;(++i)”;如果你写过,你需要使用反引号来防止&lt;int&gt;被解释为html标签。
  • 只是要清楚一点 - ((++y) * (++y)) 就程序文本中所写的内容而言,将“y”增加了两次,但这会导致未定义的行为,这意味着当程序运行时,'y' 可能会增加一次、两次、三次、从不,否则程序可能会崩溃。你只是不知道会发生什么。
【解决方案2】:

因为宏展开为:

++y * ++y

在 C++ 中给出未定义的行为 - 结果可能 成为任何东西。这个众所周知的问题应该包含在任何涵盖宏使用的体面的教科书中。你用的是哪一个?

【讨论】:

  • 您还可以看到 6x7=42,具体取决于您的编译器。
  • @Will - 否则你可能得不到 42。
【解决方案3】:

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

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

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

所以要小心宏,最好使用函数,因为编译器可以内联扩展,不会再花更多时间运行。

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

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-11
      相关资源
      最近更新 更多