C中的预处理程序命令是否计为令牌?

Ami*_*mit -1 c token c-preprocessor

我正在阅读关于令牌和计算程序中令牌数量的内容.

以前我在某处读过预处理器命令不算作令牌.但是当我在Geeksforgeeks上阅读有关令牌时,它会在"特殊符号"部分中给出:

预处理器(#):预处理器是一个宏处理器,编译器会在实际编译之前自动转换程序.

所以我很困惑,在一个程序中,如果我们写#define它将是一个令牌吗?

例如:

#include<stdio.h> 
#define max 100 
int main() 
{ 
    printf("max is %d", max); 
    return 0; 
} 
Run Code Online (Sandbox Code Playgroud)

这个例子中有多少个令牌.

zwo*_*wol 6

链接的文章充满了基本错误,不应该依赖.

解析C或C++的过程定义为一系列转换:1

  1. 反斜杠换行没有任何东西 - 甚至不是空格.
  2. 删除注释并替换为每个单独的空格.
  3. 幸存的文本被转换为一系列预处理令牌.这些特定于语言本身使用的标记的特定性:例如,关键字if是适当语言的IF标记,但只是预处理器的IDENT标记.
  4. 执行预处理指令并扩展宏.
  5. 每个预处理令牌都转换为令牌.
  6. 令牌流被解析为抽象语法树,其余编译器从那里获取它.

你的示例程序

#include<stdio.h> 
#define max 100 
int main() 
{ 
    printf("max is %d", max); 
    return 0; 
}
Run Code Online (Sandbox Code Playgroud)

将在转换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:}
Run Code Online (Sandbox Code Playgroud)

指令仍然存在于此阶段.请注意,#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
Run Code Online (Sandbox Code Playgroud)

然而,'n'中有很多令牌来自stdio.h.

预处理指令(#include,#define,#if等)始终从令牌流中删除,也许用别的东西代替,所以你永远不会有改造后6令牌可以直接从指令行的文字结果.但是你通常会有每个指令的效果产生的令牌,例如内容stdio.hDECIMAL-INTEGER:100替换IDENT:max.

最后,C和C++ 几乎完成了这一系列的操作,但并不完全相同,并且规范是正式独立的.您通常可以依赖预处理操作在两种语言中表现相同,只要您只使用预处理器执行简单操作,这无论如何都是最佳实践.


1您有时会看到人们谈论翻译阶段,这是C和C++标准正式描述这一系列操作的方式.我的清单不是翻译阶段的清单; 它包含了标准分组为单个阶段的某些内容的单独项目符号,并省略了与此讨论无关的几个步骤.