#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 = 1
和BETA = 2
.
有人可以解释一下这两者之间有什么区别吗?
使用#define
创建的预处理器宏是文本替换。
这两个例子并不等同。 第一组BETA
2-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 = %dn", 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
。宏扩展结束后,BETA
将替换为2-1*2
(由于运算符优先级(等于2-(1*2)=0
当您在">ALPHA
的值"周围添加括号时(ALPHA
实际上没有值,因为宏只是文本替换(,您将更改操作的计算顺序。现在BETA
被等于 2 的(2-1)*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来帮助您(括号指数乘法除法加法减法(,它本身可以记住为"请原谅我亲爱的萨莉阿姨"。首字母缩略词中的第一个运算必须始终在首字母缩略词中的后续运算之前完成(乘法和除法除外(在等式中,您只需从左到右,因为它们被认为具有相同的优先级,以及加法和减法(与乘法和除法相同的情况(。
C/C++ 中的宏只是文本替换,而不是函数。因此,宏的存在只是为了在编译器事件尝试分析代码之前将程序文本中的宏名称替换为其内容。因此,在第一种情况下,编译器将看到以下内容:
BETA ==> ALPHA * 2 ==> 2 - 1 * 2 ==> compiler ==> 0
printf("beta=%dn", BETA); ==> printf("beta=%dn", 2 - 1 * 2);
在第二个
BETA ==> ALPHA * 2 ==> (2 - 1) * 2 ==> compiler ==> 2
printf("beta=%dn", BETA); ==> printf("beta=%dn", (2 - 1) * 2);
- 为什么常量词在重载运算符中不与 ostream 对象一起使用<<?
- 将 [][] 运算符与向量一起使用?
- 不能将重载比较运算符与 Catch 测试一起使用
- 当返回语句时,逗号运算符、大括号初始化列表和 std::unique_ptr 组合在一起
- 为什么我不能将运算符+与reverse_iterator一起使用?
- 将流运算符与Template类一起使用
- 让类与运算符一起工作更简单的方法
- 将运算符<<与隐式转换的非基本数据类型一起使用时出错
- 为什么重载运算符不与 std::string 一起使用 msvc /MD 标志
- #define 与运算符一起使用
- 将赋值运算符与make_pair方法一起使用会生成 CLion 警告
- 是否可以将引用类型别名与指针运算符一起使用来声明对指针的引用?
- 返回对象如何与分配运算符一起工作
- 将逻辑 OR 与 cout 运算符一起使用
- 如何将模运算符与其他数据类型一起使用
- 为什么在 sizeof() 函数中与 * 运算符一起使用和不使用 * 运算符时,指向结构变量的指针大小会有所不同?
- 将[]运算符与链接列表一起使用
- 将赋值运算符与 unique_ptr 向量一起使用
- 我可以将 std:fixed 或 std::setprecision() 与>>运算符一起使用吗?
- 在C++中,我们如何将插入运算符和其他运算符链接在一起