Walter Bright 关于 C++ Compilation 的文章谈到了这两个短语
“转换为预处理令牌。”
什么是初始令牌?预处理令牌是什么样的?
“预处理令牌到 C++ 令牌的转换” 这个 C++ 令牌是什么,为什么一开始没有转换成它?
Walter Bright 关于 C++ Compilation 的文章谈到了这两个短语
“转换为预处理令牌。”
什么是初始令牌?预处理令牌是什么样的?
“预处理令牌到 C++ 令牌的转换” 这个 C++ 令牌是什么,为什么一开始没有转换成它?
预处理标记是预处理器语法的一个元素。来自 C++ 标准中的 [lex.pptoken]:
预处理令牌:
- 标题名称
- 标识符
- pp号
- 字面量
- 用户定义字符文字
- 字符串字面量
- 用户定义的字符串文字
- 预处理操作或穿孔
- 每个不能是上述之一的非空白字符
...
预处理标记是翻译阶段 3 到 6 中语言的最小词汇元素。
因此,“转换为预处理标记”是对翻译单元进行词法分析并识别单个标记的过程。
[lex.token] 中列出了 C++ 标记(实际上只是“标记”):
令牌:
- 标识符
- 关键词
- 文字
- 操作员
- 标点符号
这些仅在所有其他翻译阶段发生(宏扩展等)之后才存在。
有关整个过程的更多信息,我建议阅读 C++ 标准中的 [lex.phases]。
一个更简单的解释。
而且,您可能知道,许多编译器都有一个词法分析过程,其中源代码被拆分为标记。
这个源代码:
void main()
{
int x = -3 - -5;
printf("Hello World");
} // void main()
变成类似这样的东西:
+--------------+------------------+
| 代币 | 正文 |
+--------------+------------------+
| 无效 | “空虚” |
+--------------+------------------+
| 标识符 | “主要” |
+--------------+------------------+
| 左卷曲 | "{" |
+--------------+------------------+
| 标识符 | “整数” |
+--------------+------------------+
| 标识符 | "x" |
+--------------+------------------+
| 分配 | “=” |
+--------------+------------------+
| 减号 | "-" |
+--------------+------------------+
| 整数 | "3" |
+--------------+------------------+
| 减号 | "-" |
+--------------+------------------+
| 减号 | "-" |
+--------------+------------------+
| 整数 | "5" |
+--------------+------------------+
| 分号 | “;” |
+--------------+------------------+
| 标识符 | “打印” |
+--------------+------------------+
| 左派 | "(" |
+--------------+------------------+
| 字符串 | “你好世界” |
+--------------+------------------+
| 正确的 | ")" |
+--------------+------------------+
| 分号 | “;” |
+--------------+------------------+
| 右卷曲 | "}" |
+--------------+------------------+
| 评论 | "// 无效 main()" |
+--------------+------------------+
每一段被称为“令牌”的文本都有其含义。
有时,在编译过程的其他部分,标记可能会被其他标记替换:
+--------------+------------------+
| 代币 | 正文 |
+--------------+------------------+
| 无效 | “空虚” |
+--------------+------------------+
| 函数dec | “主要” |
+--------------+------------------+
| 左卷曲 | "{" |
+--------------+------------------+
| 类型 | “整数” |
+--------------+------------------+
| 变量dec | "x" |
+--------------+------------------+
| 分配 | “=” |
+--------------+------------------+
| 负| "-" |
+--------------+------------------+
| 整数 | "3" |
+--------------+------------------+
| 减 | "-" |
+--------------+------------------+
| 负| "-" |
+--------------+------------------+
| 整数 | "5" |
+--------------+------------------+
| 分号 | “;” |
+--------------+------------------+
| 函数调用 | “打印” |
+--------------+------------------+
| 左派 | "(" |
+--------------+------------------+
| 字符串 | “你好世界” |
+--------------+------------------+
| 正确的 | ")" |
+--------------+------------------+
| 分号 | “;” |
+--------------+------------------+
| 右卷曲 | "}" |
+--------------+------------------+
| 评论 | "// 无效 main()" |
+--------------+------------------+
从“减号”标记到“负号标记”和“减法标记”的转换是“预处理标记”到“最终标记”的一个很好的例子。
这是一个非常概念化的解释。您可能希望阅读有关特定编译器文档的更详细的技术信息。
干杯