Ele*_*kie 7 c translation-unit
如果我们有两个.c文件和一个.h文件:main.c sub.c sub.h,其中
main.c中
#include "sub.h"
...
Run Code Online (Sandbox Code Playgroud)
sub.c
#include "sub.h"
...
Run Code Online (Sandbox Code Playgroud)
我们可以编译程序,或者i)
gcc -o a.out main.c sub.c
Run Code Online (Sandbox Code Playgroud)
或ii)
gcc -c main.c
gcc -c sub.c
gcc -o a.out main.o sub.o
Run Code Online (Sandbox Code Playgroud)
鉴于这种情况,预处理器输出一个或两个翻译单元吗?
我很困惑,因为:main.c包含sub.h,意味着预处理器将输出一个编译单元.另一方面,创建了两个目标文件,main.o并且sub.o在创建可执行文件之前,让我认为"两个源文件因此有两个翻译单元".
我误解了哪一部分?或者我在哪里犯错误?
考虑将可执行文件生成为两步过程:首先,将每个翻译单元编译为目标文件; 让我们称之为编译器.其次,目标文件链接到可执行程序; 让我们称之为链接器.
"翻译单位"是第一步.翻译单元是编译开始的每个文件(即传递给编译器的文件).在大多数IDE中,有规则声明每个带扩展名的文件.c或.cpp作为输入传递给编译器,而其他文件则不是.因此,带有扩展名的文件.h,.hpp,.txt通常不直接传递到编译器.
在您的示例中,main.c并且sub.c可能是翻译单元,而sub.h不是单独的翻译单元(它仅在其他翻译单元中"包含"并在编译过程中考虑).
所以你得到两个目标文件,每个翻译单元一个.然后链接器会考虑这两个目标文件.
请注意,即使.h文件可能包含完整的程序; 但除非您将环境配置为此.h-file自行编译,否则它不会生成目标文件.
以下是 C 标准对此的规定:
\n\n\n\n\n源文件以及通过预处理指令包含的所有标头和源文件一起
\n#include称为预处理翻译单元。经过预处理后的预处理翻译单元称为翻译单元。[..] 以前翻译的翻译单元可以单独保存或保存在库中。程序的单独翻译单元通过(例如)调用其标识符具有外部链接的函数、对其标识符具有外部链接的对象的操作或对数据文件的操作来进行通信。翻译单元可以单独翻译,然后链接以产生可执行程序。
(来源:C99标准草案,5.1.1.1\xc2\xa71)
\n\n因此,在这两种情况下,您都有两个翻译单元。其中之一来自编译器预处理main.c以及通过指令包含的所有内容#include- 即,sub.h可能<stdio.h>还有其他标头。第二个来自编译器做同样的事情sub.c.
第一个示例与第二个示例的区别在于,在后者中,您显式地将“不同翻译的翻译单元”存储为目标文件。
\n\n请注意,没有任何规则将一个目标文件与任意数量的翻译单元相关联。GNU 链接器是能够将两个.o文件连接在一起的链接器示例之一。
据我所知,该标准没有指定源文件的扩展名。尽管如此,在实际方面,您可以自由地将#include一个.c文件放入其他文件中,或者将整个程序放入一个.h文件中。gcc您可以使用该选项强制-x c将.h文件视为翻译单元的起点。
这里做出的区分:
\n\n\n\n\n源文件以及通过预处理指令包含的所有标头和源文件
\n#include[...]
是因为标头不必是源文件。<...>同样,指令中的内容#include不必是有效的文件名。编译器究竟如何使用命名标头<...>并由"..."实现定义。
| 归档时间: |
|
| 查看次数: |
516 次 |
| 最近记录: |