我正在阅读有关 token 的内容并计算程序中 token 的数量。
之前我在某处读到预处理器命令不计为 token 。 但是当我在 Geeksforgeeks 上读到有关代币的信息时它在“特殊符号”部分给出:
pre processor(#): The preprocessor is a macro processor that is used automatically by the compiler to transform your program before actual compilation.
所以我很困惑,在程序中,如果我们写#define
,它会是一个 token 吗?
例如:
#include<stdio.h>
#define max 100
int main()
{
printf("max is %d", max);
return 0;
}
此示例中有多少个 token ?
最佳答案
链接的文章充满了基本错误,不应依赖。
解析 C 或 C++ 的过程被定义为一系列转换:1
- 反斜杠换行符不被任何内容替换——甚至连空格也没有。
- 评论将被删除并替换为一个空格。
- 剩余文本被转换为一系列预处理标记。这些比语言本身使用的标记不太具体:例如,关键字
if
是语言本身的 IF 标记,但对于预处理器来说只是 IDENT 标记。 - 执行预处理指令并扩展宏。
- 每个预处理标记都会转换为一个标记。
- 标记流被解析为抽象语法树,编译器的其余部分从那里获取它。
您的示例程序
#include<stdio.h>
#define max 100
int main()
{
printf("max is %d", max);
return 0;
}
在转换 3 之后,将成为这一系列 23 个预处理标记:
PUNCT:# IDENT:include INCLUDE-ARG:<stdio.h>
PUNCT:# IDENT:define IDENT:max PP-NUMBER:100
IDENT:int IDENT:main PUNCT:( PUNCT:)
PUNCT:{
IDENT:printf PUNCT:( STRING:"max is %d" PUNCT:, IDENT:max PUNCT:) PUNCT:;
IDENT:return PP-NUMBER:0 PUNCT:;
PUNCT:}
现阶段这些指令仍然存在。请注意,#include
和 #define
各是两个标记:#
和指令名称是分开的。有些人喜欢编写复杂的 #if
嵌套,其中井号标记全部位于第 1 列,但指令名称缩进。
但是,在转换 5 之后,指令消失了,我们有了这一系列 16+n 个标记:
[ ... some large volume of tokens produced from the contents of stdio.h ... ]
INT IDENT:main LPAREN RPAREN
LBRACE
IDENT:printf LPAREN STRING:"max is %d" COMMA DECIMAL-INTEGER:100 RPAREN SEMICOLON
RETURN DECIMAL-INTEGER:0 SEMICOLON
RBRACE
其中“n”表示来自 stdio.h 的 token 数量。
预处理指令(#include
、#define
、#if
等) 始终从 token 流,并且可能替换为其他内容,因此在转换 6 之后,您将永远不会拥有直接由指令行文本产生的 token 。但您通常会拥有由每个指令的效果产生的标记,例如 stdio.h
和 DECIMAL-INTEGER:100
的内容> 替换 IDENT:max
。
最后,C 和 C++ 所做的这一系列操作几乎,但又不完全相同,而且规范在形式上是独立的。您通常可以依靠预处理操作在两种语言中表现相同,只要您只使用预处理器执行简单的操作,无论如何,这都是当今的最佳实践。
<小时/>1 有时您会看到人们谈论翻译阶段,这是 C 和 C++ 标准正式描述这一系列操作的方式。我的列表不是翻译阶段的列表;它包含一些按标准分组为单个阶段的单独要点,并省略了与本讨论无关的几个步骤。
关于c - C 中的预处理器命令算作 token 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52468375/