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()" | +--------------+------------------+
从“减号”标记到“负号标记”和“减法标记”的转换是“预处理标记”到“最终标记”的一个很好的例子。
这是一个非常概念化的解释。您可能希望阅读有关特定编译器文档的更详细的技术信息。
干杯