c++ - 为什么要在宏扩展之前进行代币替换?
问题描述
考虑以下代码段:
#include <stdio.h>
#define MY_MACRO(\
arg) \
arg
#define MY_MACRO2(t1, t2) t1##t2
#define MY_ a
#define MACRO b
int main() {
printf("%d\n", MY_MACRO2(MY_,MACRO)(45));
return 0;
}
结果是编译并显示 45,但是,如果MY_
和MACRO
在替换之前被扩展,则此代码不应编译。我注意到这一点的原因是当我在 C 标准中阅读以下内容时:
6.10.3.1(但也符合 C++ 标准)
在确定了调用类函数宏的参数后,将进行参数替换。替换列表中的参数,除非前面有 # 或 ## 预处理标记或后跟 ## 预处理标记(见下文) ,在其中包含的所有宏都被扩展后被相应的参数替换 。在被替换之前,每个参数的预处理标记都被完全宏替换,就好像它们形成了预处理文件的其余部分一样;没有其他可用的预处理令牌
因此,如果参数中包含的所有宏在替换之前都已扩展,为什么我们不以ab(45)
?
解决方案
让建筑像X(X())
工作一样。请注意,在X()
扩展X
宏时,宏被禁用以避免无限递归。在扩展宏之前扩展参数让我们在参数中使用 X。的实际应用X(X())
:
#define TEN(x) x x x x x x x x x x
#define HUNDRED(x) TEN(TEN(x))
推荐阅读
- python - 为什么我在 Python 中收到断言错误?
- python - Python 根据 char 长度拆分 int
- python - python脚本从csv文件中获取实例ID并启动实例
- c# - C# Windows 窗体 - 需要初学者指导 - 仅在两个文本框输入字符时启用按钮
- c# - 无法将 int 类型隐式转换为系统集合泛型列表
- c - 如何在 c 中处理这种消息 - 'objectFromFile' 的冲突类型
- javascript - 不能用 jasmine/karma 和 typecpript 模拟“窗口”
- html - 我怎样才能让文本正确对齐,但 div 对齐中心?
- express - 将帖子响应加载到现有的 html 页面中
- swift - 为什么 UIAlertAction 的处理程序需要有一个引用 UIAlertAction 的参数?