#define 宏不如预期

#define macro doesn't as expect

本文关键字:#define      更新时间:2023-10-16

我在测试中弄错了这个问题,真的很困惑为什么。

对于下面的给定代码,我认为输出将为 0。有人可以解释为什么不是吗?

#include<iostream>
using namespace std;
#define A 0
#define B A+1
#define C 1-B
int main{
cout<<C;
return(0);
}

正确答案(和实际输出(是 2。

如果您逐步扩展宏,您将获得正确答案。

cout<<C;

cout<<1-B;

cout<<1-A+1;

cout<<1-0+1;

这是

cout << 2;

请记住,宏不像变量那样工作。如果你使用变量,你会得到不同的答案。

int a = 0;
int b = a+1;  // b is 1.
int c = 1-b;  // c is 0
cout << c;    // Expect 0 in output.

预处理器通过执行文本替换和生成随后编译的代码来扩展宏。 预处理器(大多数(不理解表达式 - 由编译的后期阶段(预处理器完成后(处理。

所以C扩展到1-B扩展1-A+1扩展到1-0+1

编译器将其视为表达式。1-0+12

要获得预期的结果(零(,您需要使用

#define A 0
#define B (A+1)
#define C (1-B)

所以C扩展到(1-B)扩展(1-(A+1))扩展到(1-(0+1)),它被计算(由编译器,而不是预处理器(作为表达式并给出0

请记住,ABC不是变量。 它们是宏 - 即指向预处理器的有关如何进行文本替换的说明。

我以为输出会是0。有人可以解释为什么 不是吗?

因为C扩展到1-B

现在,B扩展到A+1.

现在,A再次扩展到0


填补空白:

由于A扩展到0,因此B0+1取代

然后替换表达式中的B1-B就变得1-0+1

C = 1-B
//    ^^^
//      A+1
//      ^^^
//
//  = 1-0+1

宏是C89,c++11在编译时提供了一个更好的解决方案:constexpr。

#include<iostream>
using namespace std;
constexpr auto A = 0;
constexpr auto B = A + 1;
constexpr auto C = 1 - B;
int main{
cout<<C;
return(0);
}

优点是:更易于使用,因为您已经知道语法和行为。不允许未定义的行为,这使得这更安全。而且你不能让循环依赖产生奇怪的副作用,否则它不会编译。