算术表达式背景下的宏观扩展

Macro expansion in context of arithmetic expression?

本文关键字:宏观 扩展 背景 表达式      更新时间:2023-10-16

我在网站上看到了下面的代码。我无法理解结果是如何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");
}

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

在您的示例中,SQ(2 + 3)扩展到 (2 + 3*2 + 3) ,其计算结果为 11

定义SQ的更可靠方法是:

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

现在,SQ(2 + 3)将扩展到((2 + 3)*(2 + 3)),给25

尽管这个定义是一个改进,但它仍然不是防弹的。如果SQ()应用于有副作用的表达式,这可能会产生不良后果。例如:

  • 如果f()是一个将某些内容打印到控制台并返回int的函数,SQ(f())将导致输出被打印两次。
  • 如果iint变量,则SQ(i++)会导致未定义的行为。

有关宏困难的更多示例,请参阅宏陷阱。

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

#define扩展在编译器看到源代码之前启动。这就是为什么它们被称为预处理器指令,这里的处理器是将 C 转换为机器可读代码的编译器。

因此,这就是宏预处理器传递给编译器的内容:

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

所以,这真的是2 + 6 + 3 = 11 .

怎么能让它做你期望的?

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

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

SQ(2 + 3)

到:

2 + 3*2 + 3

简化为:

2 + 6 + 3

这是 11。

#define preprocesor

语法: # 定义标识符替换

  1. 当预处理器遇到此指令时,它会通过替换代码其余部分中出现的任何标识符。
  2. 这种替换可以是表达式、语句、块或简单的任何东西。
  3. 预处理器不理解 C,它只是通过替换替换任何出现的标识符。

# define 也可以使用参数来定义函数宏:

# define SQ(a) (a*a)

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

SQ(2+3) 将被 2+3

*2+3 取代计算在更换完成后执行。因此回答 2+3*2+3=11

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

您应该将其定义为:

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

gcc上测试,用于输入,例如

  1. 常数
  2. 变量
  3. 常量
  4. +常量
  5. 常量+变量
  6. 变量++/++变量
  7. 函数调用,包含 printf。

注意:typeof是 GNU 对标准 C 的补充,在某些编译器中可能不可用。

它只是编译前的替换

所以你应该试试这个:

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

在你的情况下,SQ(2 + 3)等价于11 (2+3*2+3)

但是把它改成我上面写的,它会像,((2+3)*(2+3))哪个5*5 = 25这就是你想要的答案。