预处理器和编译器之间的边界到底在哪里?
根据各种来源(例如,SE Kevlin Henney 的广播节目,如果我没记错的话),“带有类的 C”是通过预处理器技术实现的(然后输出被馈送到 C 编译器),而 C++ 始终是通过编译器实现的(即只是正好早期吐出了C)。这似乎引起了一些混乱,所以我想知道:
预处理器和编译器之间的边界到底在哪里?什么时候将实现某种语言的软件称为“预处理器”,什么时候将其称为“编译器”?
顺便问一下,“编译语言”是一个既定术语吗?如果是这样,这到底意味着什么?
According to various sources (for example, the SE radio episode with Kevlin Henney, if I remember correctly), "C with classes" was implemented with preprocessor technology (with the output then being fed to a C compiler), whereas C++ has always been implemented with a compiler (that just happened to spit out C in the early days). This seems to cause some confusion, so I was wondering:
Where exactly is the boundary between a preprocessor and a compiler? When do you call a piece of software that implements a language "a preprocessor", and when do you call it "a compiler"?
By the way, is "a compiled language" an established term? If so, what exactly does it mean?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
编译器由多个进程(组件)组成。预处理器只是其中之一,也是相对最简单的一种。
从维基百科文章,编译器进程的划分:
预处理只是前端工作的一小部分。
第一个通过在现有 C 编译器工具集前面附加附加进程而制成的 C++ 编译器,不是因为它设计得好,而是因为 认为这种非原生 C++编译
器无法在商业领域生存。
如今,我 rel="nofollow">
cfront
用于C++11
是不可能制作的。A compiler consist of serval processes (components). The preprocessor is only one of these and relatively most simple one.
From the Wikipedia article, Division of compiler processes:
Preprocessing is only the small part of the front end job.
The first C++ compiler made by attaching additional process in front of existing C compiler toolset, not because it is good design but because limited time and resources.
Nowadays, I don't think such non-native C++ compiler can survive in the commercial field.
I dare say
cfront
forC++11
is impossible to make.答案很简单。
预处理器将文本作为输入并以文本作为输出。例如,旧的 unix 命令 m4、cpp(C 预处理器)以及 roff、nroff 和 troff 等 unix 程序,它们用于(并且仍然)格式化手册页(unix 命令“man”)或格式化文本用于打印或排版。
预处理器非常简单,它们对它们处理的“文本语言”一无所知。换句话说,它们通常处理自然语言。 C 预处理器除了它的名称之外,例如仅识别#define、#include、#ifdef、#ifndef、#else 等,如果您使用#define MACRO,它会尝试在它找到的任何地方“扩展”该宏。但这不一定是 C 或 C++ 程序文本,它也可以是用意大利语或希腊语写的小说。
交叉编译成不同语言的编译器通常称为翻译器。因此,发出 C 代码的 C++ 旧 cfront“编译器”是一个 C++ 翻译器。
历史上一直使用预处理器和后来的翻译器,因为旧机器根本缺乏内存,无法在一个程序中完成所有操作,而是由专门的程序从一个磁盘到另一个磁盘完成。
典型的 C 程序可以从各种来源编译。构建过程将由 make 管理。如今,C 预处理器通常直接构建到 C/C++ 编译器中。典型的 make 运行会在 *.c 文件上调用 CPP 并将输出写入不同的目录,C 编译器 CC 会从那里将其直接编译为机器代码,或更常见的是会将汇编代码输出为文本。注意:C 编译器仅检查语法,它并不真正关心类型安全等。然后汇编器将采用该汇编器代码并输出一个 *.o 文件,稍后可以将其与其他 *.o 文件和 *.lib 链接文件转化为可执行程序。 OTOH,您可能有一个 make 规则,它不会调用 C 编译器,而是调用 lint 命令,即 C 语言分析器,它会查找典型的错误和错误(这些错误会被 C 编译器忽略)。
在维基百科(或使用 man 的机器终端)上查找有关 lint、nroff、troff、m4 等的信息非常有趣;D
The answer is pretty simple.
A preprocessor works on text as input and has text as output. Examples for that are the old unix commands m4, cpp (the C Pre Processor), and also unix programs like roff and nroff and troff which where used (and still are) to format man pages (unix command "man") or format text for printing or typesetting.
Preprocessors are very simple, they don't know anything about the "language of the text" they process. In other words they usually process natural languages. The C preprocessor besides its name, e.g. only recognizes #define, #include, #ifdef, #ifndef, #else etc. and if you use #define MACRO it tries to "expand" that macro everywhere it finds it. But that does not need to be C or C++ program text, it can as well be a novel written in italian or greek.
Compilers that cross compile into a different language are usually called translators. So the old cfront "compiler" for C++ which emitted C code was a C++ translator.
Preprocessors and later translators are historically used because old machines simply lacked memory to be able to do everything in one program, but instead it was done by specialized programs and from disk to disk.
A typical C program would be compiled from various sources. And the build process would be managed with make. In our days the C preprocessor is usually build directly into the C/C++ compiler. A typical make run would call the CPP on the *.c files and write the output to a different directory, from there either the C compiler CC would compile it straight to machine code or more commonly would output assembler code as text. Note: the c compiler only checks syntax, it does not really care about type safety etc. Then the assembler would take that assembler code and would output a *.o file wich later can be linked with other *.o files and *.lib files into an executable program. OTOH you likely had a make rule that would not call the C compiler but the lint command, the C language analyser, which is looking for typical mistakes and errors (which are ignored by the c compiler).
It is quite interesting to look up about lint, nroff, troff, m4 etc. on wikipedia (or your machines terminal using man) ;D
这是一个有趣的问题。我不知道一个明确的答案,但如果迫不得已,我会这么说:
This is an interesting question. I don't know a definitive answer, but would say this, if pressed for one:
预处理器的输出语言是输入语言的子集。
编译器输出的语言(通常)与输入的语言(机器代码)非常不同。
The language of the output of the preprocessor is a subset of the language of the input.
The language of the output of the compiler is (usually) very different (machine code) then the language of the input.
从简化的、个人的角度来看:
我认为预处理器是任何形式的文本操作,没有底层语言的概念(即:语义或结构),因此仅依赖于它自己的一组规则来执行它的操作。职责。
当规则和规定应用于正在处理的内容时,编译器启动(是的,它使“我的”预处理器成为编译器,但为什么不:P),这包括符号和词法检查,以及包含的从 x(文本)到y(二进制/中间形式)。正如我的一位教授所说:“它是一个具有输入、流程和输出的系统”。
From a simplified, personal, point of view:
I consider the preprocessor to be any form of textual manipulation that has no concepts of the underlying language (ie: semantics or constructs), and thus only relies on its own set of rules to perform its duties.
The compiler starts when rules and regulation are applied to what is being processed (yes, it makes 'my' preprocessor a compiler, but why not :P), this includes symantical and lexical checking, and the included transforms from x (textual) to y (binary/intermediate form). as one of my professors would say: "its a system with inputs, processes and outputs".
C/C++ 编译器关心类型正确性,而预处理器只是扩展符号。
The C/C++ compiler cares about type-correctness while the preprocessor simply expands symbols.