#define 与运算符一起使用

#define used with operators

我知道 #define 的语法如下:#define SYMBOL string 如果我写,例如

#define ALPHA 2-1
#define BETA ALPHA*2

然后 ALPHA = 1 但是 BETA = 0。(为什么?)

但是如果我这样写

#define ALPHA (2-1)
#define BETA ALPHA*2

然后 ALPHA = 1BETA = 2

谁能给我解释一下这两者有什么区别?

运算顺序。第一个例子变为 2-1*2,等于 2-2。 另一方面,第二个示例扩展为 (2-1)*2,计算结果为 1*2.

在第一个例子中:

#define ALPHA 2-1
#define BETA ALPHA*2

alpha 直接替换为您给它的任何值(在本例中为 2-1)。 这导致 BETA 扩展为(成为)2-1*2,其计算结果为 0,如上所述。

在第二个例子中:

#define ALPHA (2-1)
#define BETA ALPHA*2

Alpha(在 BETA 的定义中)扩展到它设置的值 (2-1),然后导致 BETA 在使用时扩展到 (2-1)*2。

如果您在运算顺序上遇到问题,您可以随时使用首字母缩略词 PEMDAS 来帮助您(括号指数乘法除法加法减法),它本身可以是记为 "Please Excuse My Dear Aunt Sally"。首字母缩略词中的第一个运算必须始终在首字母缩略词中的后续运算之前完成(乘法和除法除外(在等式中你只需从左到右,因为它们被认为具有相同的优先级,加法和除法减法(与乘法和除法相同的场景)。

使用 #define 创建的预处理器宏是 文本 替换。

这两个例子并不等同。第一个设置 BETA2-1*2。第二个将 BETA 设置为 (2-1)*2。像你这样声称ALPHA == 1是不正确的,因为ALPHA不是一个数字 - 它是一个自由人! 这只是一个字符序列。

当解析为 C 或 C++ 时,这两个表达式不同(第一个与 2 - (1*2) 相同)。

我们可以通过打印 BETA 的字符串扩展并将其作为表达式求值来显示差异:

#ifdef PARENS
#define ALPHA (2-1)
#else
#define ALPHA 2-1
#endif

#define BETA ALPHA*2

#define str(x) str2(x)
#define str2(x) #x

#include <stdio.h>
int main()
{
    printf("%s = %d\n", str(BETA), BETA);
    return 0;
}

在定义和不定义 PARENS 的情况下编译上面的内容以查看区别:

(2-1)*2 = 2
2-1*2 = 0

这样做的结果是,当使用 #define 创建扩展为表达式的宏时,使用比通常需要更多的括号通常是个好主意,因为您不知道上下文您的价值观将在其中得到扩展。例如:

#define ALPHA (2-1)
#define BETA ((ALPHA)*2)

宏 (#define ...) 只是文本替换。

使用此版本:

#define ALPHA 2-1
#define BETA ALPHA*2

预处理器将 BETA 替换为 ALPHA*2,然后将 ALPHA 替换为 2-1。当宏扩展结束时,BETA2-1*2 替换,后者(由于运算符优先级)等于 2-(1*2)=0

当您在“ ALPHA 的值”两边添加括号时(ALPHA 实际上没有值,因为宏只是文本替换),您更改操作的评估顺序。现在 BETA(2-1)*2 代替,等于 2.

c/c++ 中的宏只是文本替换,不是函数。因此,在编译器事件尝试分析代码之前,宏只是用其内容 替换程序文本中的宏名称 。所以在第一种情况下,编译器会看到:

BETA ==> ALPHA * 2 ==> 2 - 1 * 2 ==> compiler ==> 0
printf("beta=%d\n", BETA); ==> printf("beta=%d\n", 2 - 1 * 2);

第二个

BETA ==> ALPHA * 2 ==> (2 - 1) * 2 ==> compiler ==> 2
printf("beta=%d\n", BETA); ==> printf("beta=%d\n", (2 - 1) * 2);