c - C 中的预处理器命令算作 token 吗?

标签 c c-preprocessor token

我正在阅读有关 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

  1. 反斜杠换行符不被任何内容替换——甚至连空格也没有。
  2. 评论将被删除并替换为一个空格。
  3. 剩余文本被转换为一系列预处理标记。这些比语言本身使用的标记不太具体:例如,关键字 if 是语言本身的 IF 标记,但对于预处理器来说只是 IDENT 标记。
  4. 执行预处理指令并扩展宏。
  5. 每个预处理标记都会转换为一个标记。
  6. 标记流被解析为抽象语法树,编译器的其余部分从那里获取它。

您的示例程序

#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.hDECIMAL-INTEGER:100 的内容> 替换 IDENT:max

最后,C 和 C++ 所做的这一系列操作几乎,但又不完全相同,而且规范在形式上是独立的。您通常可以依靠预处理操作在两种语言中表现相同,只要您只使用预处理器执行简单的操作,无论如何,这都是当今的最佳实践。

<小时/>

1 有时您会看到人们谈论翻译阶段,这是 C 和 C++ 标准正式描述这一系列操作的方式。我的列表不是翻译阶段的列表;它包含一些按标准分组为单个阶段的单独要点,并省略了与本讨论无关的几个步骤。

关于c - C 中的预处理器命令算作 token 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52468375/

相关文章:

c++ - 宏重复几乎相同的代码

objective-c - 静态库中的预处理器宏

c# - 从 AAD 登录获取 token

c - 简单的for循环无限运行

c线程;快速便携?

我可以同时使用 scanf 和 getchar 来读取文件吗?

c++ - 如果在 C++ 中,则为预处理器

c - 是否可以将预定义大小的数组传递给 C 函数,以便可以在该函数中使用 `sizeof` 检索其大小?

session - AEM - 获取当前用户ID

drupal - 刷新现有节点以获取 Drupal 中的自动节点标题