算术表达式中的宏扩展?

我在网站上看到了以下代码。 我无法判断结果如何变为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"); } 

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

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

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

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

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

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

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

在您的示例中, 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++)导致未定义的行为 。

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

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

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

 SQ(2 + 3) 

成:

 2 + 3*2 + 3 

这简化为:

 2 + 6 + 3 

这是11。

#define preprocesor

语法: #define identifier replacement

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

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

# define SQ(a) (a*a)

将在编译时用* a替换任何SQ(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. 函数调用,包含printf。

注意: typeof是标准C的GNU添加。可能在某些编译器中不可用。

它只是编译前的替代品

所以你应该试试这个:

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

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

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