我正在阅读有关令牌的内容并计算程序中令牌的数量。
之前我在某处读到预处理器命令不计为令牌。 但是当我在 Geeksforgeeks 上读到有关令牌时,它在“特殊符号”部分中给出:
预处理器(#):预处理器是编译器自动使用的宏处理器,用于在实际编译之前转换程序。
所以我很困惑,在程序中,如果我们写
#define
,它会是一个令牌吗?
例如:
#include<stdio.h>
#define max 100
int main()
{
printf("max is %d", max);
return 0;
}
这个例子中有多少个代币?
链接的文章充满了基本错误,不应依赖。
解析 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
分别是 two 标记:#
和指令名称是分开的。有些人喜欢编写复杂的 #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 OCTAL-INTEGER:0 SEMICOLON
RBRACE
其中“n”表示来自 stdio.h 的令牌数量。
预处理指令(
#include
、#define
、#if
等)are始终从令牌流中删除,并且可能用其他内容替换,因此在转换 6 之后,您永远不会拥有直接从文本产生的令牌一条指令线。但您通常会拥有由每个指令的 effects 产生的标记,例如 stdio.h
的内容,以及 DECIMAL-INTEGER:100
替换 IDENT:max
。
最后,C 和 C++ 做这一系列操作几乎,但又不完全一样,而且规范在形式上是独立的。您通常可以依靠预处理操作在两种语言中表现相同,只要您只使用预处理器做简单的事情,无论如何,这是当今的最佳实践。
1 有时你会看到人们谈论翻译阶段,这是 C 和 C++ 标准正式描述这一系列操作的方式。我的列表不是翻译阶段的列表;它包含一些按标准分组为单个阶段的单独要点,并省略了与本讨论无关的几个步骤。