算术表达式上下文中的宏扩展?

时间:2012-12-05 07:27:59

标签: c++ c

我在网站上看到了以下代码。 我无法用11代替2513来判断结果的结果。

为什么我在考虑25,因为SQ(5) 5*5

13因为

SQ(2) = 4;

SQ(3) = 9;

可能是最终结果13 (9 + 4) 但惊讶地看到结果为11。 结果如何11

using namespace std;
#define SQ(a) (a*a)
int main()
{
    int ans = SQ(2 + 3);
    cout << ans << endl;
system("pause");
}

6 个答案:

答案 0 :(得分:19)

预处理器在源代码上执行简单的文本替换。它对底层语言或其规则一无所知。

在您的示例中,SQ(2 + 3)展开为(2 + 3*2 + 3),评估为11

定义SQ的更有效方法是:

#define SQ(a) ((a)*(a))

现在,SQ(2 + 3)会扩展为((2 + 3)*(2 + 3)),并提供25

即使这个定义是一种改进,它仍然不是防弹的。如果将SQ()应用于side effects的表达式,则可能会产生不良后果。例如:

  • 如果f()是一个向控制台打印内容并返回int的函数,则SQ(f())会导致输出打印两次。
  • 如果iint变量,SQ(i++)会产生undefined behaviour

有关宏的困难的更多示例,请参阅Macro Pitfalls

由于这些原因,通常最好使用函数而不是宏。

答案 1 :(得分:6)

在编译器看到源代码之前,

#define扩展就开始了。这就是为什么它们被称为预处理器指令,这里的处理器是将C转换为机器可读代码的编译器。

所以,这就是宏预处理器传递给编译器的原因:

SQ(2 + 3)扩展为(2 + 3*2 + 3)

所以,这确实是2 + 6 + 3 = 11

你怎么能做到你期望的呢?

  1. 执行评估顺序。在宏定义或宏调用中使用()。 OR
  2. 编写一个完成工作的简单函数

答案 2 :(得分:3)

C预处理器在编译器解释表达式和C语法之前进行文本替换。因此,在此代码上运行C预处理器会转换:

SQ(2 + 3)

成:

2 + 3*2 + 3

简化为:

2 + 6 + 3

这是11。

答案 3 :(得分:1)

这只是编译前的替代

所以你应该尝试一下:

#define SQ(a) ((a)*(a))

在您的情况下,SQ(2 + 3)相当于(2+3*2+3) 11

但正如我在上面所写的那样纠正它,就像((2+3)*(2+3))那样5*5 = 25就是你想要的答案。

答案 4 :(得分:1)

#define preprocesor

语法:   #define identifier replacement

  1. 当预处理器遇到此指令时,它会通过替换替换其余代码中出现的任何标识符。
  2. 这种替换可以是表达,陈述,块或任何东西。
  3. 预处理器不理解C,它只是通过替换替换任何出现的标识符。
  4. #define也可以使用参数来定义函数宏:

    <强> # define SQ(a) (a*a)

    将在编译时用* a替换任何SQ(a)的出现。 因此,

    SQ(2 + 3)将替换为2 + 3 * 2 + 3 在完成替换之后执行计算。 因此回答2 + 3 * 2 + 3 = 11

答案 5 :(得分:1)

对于您的实施,该值将扩展为2+3 * 2+3,这将导致2 + 6 + 3 = 11。

您应该将其定义为:

#define SQ(x) ({typeof(x) y=x; y*y;})

gcc上测试,输入

等输入
  1. 常数,
  2. 变量,
  3. 恒定+ const的
  4. 常量+变量
  5. 变量++ / ++变量
  6. 函数调用,包含printf。
  7. 注意:typeof是标准C的GNU添加。可能在某些编译器中不可用。