我正在阅读[让我们C-by Yashwant Kanetkar],在这里说:
当我们编译程序时,在源代码传递给编译器之前,C预处理器会检查它是否有任何宏定义。当它看到#define指令时,它会遍历整个程序以搜索宏模板;只要找到一个,它就会用适当的宏扩展替换宏模板。只有在完成此过程后,程序才会处理到编译器。
我的问题是,在程序传递给编译器之前,预处理器程序如何能够读取宏模板对应的TOKENS?预处理程序是否也能将程序划分为TOKENS。
答案 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页
中收集源程序的任务有时会委托给一个单独的程序,称为预处理程序。预处理器还可以将称为宏的缩写扩展为源语言语句。 修改后的源程序然后输入编译器 。
C预处理器是一个宏处理器,C编译器会自动使用它来在实际编译之前转换程序 。
Andn也读了this。
因此,从这三个官方来源,可以说预处理器是由Compiler运行的单独的程序。所以在书中让我们C 由Yashwant P Kanetkar预处理器是一个程序,在编译器之前进行处理,顾名思义没有错,扩展的代码可以在文件中看到。 I 强>
现在让我们回答你的问题,
在书K & R The C Programming Language。
Page No:89
仅对令牌进行替换,并且不会在带引号的字符串中进行替换。
正如Basile在答案中所说的那样
在当前的C编译器中(出于性能原因)预处理器不再是一个单独的程序,它是编译器本身的一部分。
并且编译是一个经过几个phases的漫长过程,预处理器实际上是在程序转换为标记之后出现的,但是因为消息来源说这是编译之前的过程,这意味着它已经完成在任何类型的中间代码生成之前,是的,将程序分解为令牌是编译器在任何中间代码生成之前的第一步。