【问题标题】:Are the preprocessor commands in C counted as tokens?C 中的预处理器命令是否算作标记?
【发布时间】:2018-09-23 17:03:48
【问题描述】:

我正在阅读有关令牌并计算程序中令牌数量的信息。

以前我在某处读到预处理器命令不计为令牌。 但是当我在Geeksforgeeks 上阅读有关令牌时,它在“特殊符号”部分中给出:

预处理器(#):预处理器是一个宏处理器,编译器在实际编译之前自动使用它来转换你的程序。

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

例如:

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

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

【问题讨论】:

  • 没有c/c++语言这种东西。
  • 有效令牌是什么意思? 关键字
  • 极客对极客的文章充满了可疑的解释。我会忽略这篇文章。上次我查看 C++ 语法预处理器标记和标记是不同的东西,预处理器标记算作标记。
  • 我的意思是它会被简单地算作令牌吗?请指定该程序中有多少令牌,以便我可以获得更好的知识
  • @john '#' 和 'include' 都是预处理器标记。语言中唯一没有根据某种标记定义的方面是 cmets、反斜杠换行符和三元组。

标签: c c-preprocessor token


【解决方案1】:

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

解析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。

预处理指令(#include#define#if 等)总是从令牌流中删除,并且可能被其他东西替换,因此转换后您将永远不会有令牌6 直接来自指令行的文本。但是您通常会有每个指令的效果 产生的标记,例如stdio.h 的内容和DECIMAL-INTEGER:100 替换IDENT:max

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


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

【讨论】:

    猜你喜欢
    • 2016-12-14
    • 2010-09-23
    • 1970-01-01
    • 2019-05-28
    • 2011-07-02
    • 2010-12-18
    • 1970-01-01
    • 2015-11-22
    相关资源
    最近更新 更多