预处理器指令如何在C中工作?

时间:2017-02-18 12:23:11

标签: c compilation c-preprocessor

我正在阅读[让我们C-by Yashwant Kanetkar],在这里说:

  

当我们编译程序时,在源代码传递给编译器之前,C预处理器会检查它是否有任何宏定义。当它看到#define指令时,它会遍历整个程序以搜索宏模板;只要找到一个,它就会用适当的宏扩展替换宏模板。只有在完成此过程后,程序才会处理到编译器。

我的问题是,在程序传递给编译器之前,预处理器程序如何能够读取宏模板对应的TOKENS?预处理程序是否也能将程序划分为TOKENS。

2 个答案:

答案 0 :(得分:3)

这种描述令人困惑(所以我不推荐这本书;而是阅读K&R The C Programming Language book)。预处理器不会通过整个程序,它先前已经处理了一些输入。只有过去的预处理输入才对预处理器的行为很重要(换句话说,预处理器是单通道机制)。

C preprocessor上阅读wikipage,然后阅读GNU cpp的文档和preprocessor上的其他文档以及C programming/Preprocessor上的wikibook章节。

在当前的C编译器中(出于性能原因)预处理器不再是单独的程序,它是编译器本身的一部分。对于最近的GCC,请查看libcpp/(其预处理器,编译器内部)。

如果使用GCC编译器,您可以通过运行csource.c获取source code文件gcc -C -E csource.c > csource.i的预处理形式,然后查看生成的预处理表单{{1} (例如,使用pager或编辑器。)

(我强烈建议偶尔这样做;你会学到很多东西;是的,你可能会对通常的csource.i指令提取的代码量感到惊讶< / SUP>

我相信你的书错误地解释了。预处理器处理每个预处理directive。遇到#include <stdio.h>时,它会在某些预处理器符号表中存储该符号的定义。当 #define出现该预处理程序符号后遇到时,它会进行相应的替换。

答案 1 :(得分:1)

在书K & R The C Programming Language

Page No:88

  

C通过预处理器提供某些语言功能,预处理器在概念上是编译中单独的第一步。

在书Compiler Principles, Techniques and Tools by Aho, Lam, Sethi and Ullman

第3页

  

收集源程序的任务有时会委托给一个单独的程序,称为预处理程序。预处理器还可以将称为宏的缩写扩展为源语言语句。 修改后的源程序然后输入编译器

GCC GNU Documentation

  

C预处理器是一个宏处理器,C编译器会自动使用它来在实际编译之前转换程序

Andn也读了this

因此,从这三个官方来源,可以说预处理器是由Compiler运行的单独的程序。所以在书中让我们C Yashwant P Kanetkar预处理器是一个程序,在编译器之前进行处理,顾名思义没有错,扩展的代码可以在文件中看到。 I

现在让我们回答你的问题,

在书K & R The C Programming Language

Page No:89

  

仅对令牌进行替换,并且不会在带引号的字符串中进行替换。

正如Basile在答案中所说的那样

  

在当前的C编译器中(出于性能原因)预处理器不再是一个单独的程序,它是编译器本身的一部分。

并且编译是一个经过几个phases的漫长过程,预处理器实际上是在程序转换为标记之后出现的,但是因为消息来源说这是编译之前的过程,这意味着它已经完成在任何类型的中间代码生成之前,是的,将程序分解为令牌是编译器在任何中间代码生成之前的第一步。