如果我们有两个.c文件和一个.h文件:main.c sub.c sub.h
,其中
main.c
#include "sub.h"
...
sub.c
#include "sub.h"
...
我们可以用i)编译程序
gcc -o a.out main.c sub.c
或ii)
gcc -c main.c
gcc -c sub.c
gcc -o a.out main.o sub.o
在这种情况下,预处理器会输出一个或两个翻译单元吗?
我感到困惑是因为:
main.c
包括sub.h
,这意味着预处理器将输出一个编译单元。另一方面,在创建可执行文件之前,创建了两个目标文件main.o
和sub.o
,使我认为“两个源文件即两个翻译单元”。我误解了哪一部分?还是我在哪里犯错?
最佳答案
以下是 C 标准对此的看法:
(来源:C99 标准草案,5.1.1.1 §1)
因此,在您的两种情况下,您都有两个翻译单元。其中之一来自编译器预处理 main.c
以及通过 #include
指令包含的所有内容 - 即 sub.h
以及可能的 <stdio.h>
和其他 header 。第二个来自编译器对 sub.c
做同样的事情。
从第一个示例到第二个示例的不同之处在于,在后者中,您将“不同的翻译单元”明确存储为目标文件。
请注意,没有将一个目标文件与任意数量的翻译单元相关联的规则。 GNU 链接器是 is capable of joining two .o
files together 链接器的一个示例。
据我所知,该标准没有指定源文件的扩展名。尽管如此,在实际方面,您可以自由地将 #include
文件 .c
转换为其他文件,或者将整个程序放在 .h
文件中。使用 gcc
,您可以使用选项 -x c
强制将 .h
文件视为翻译单元的起点。
这里的区别:
是因为 header 不必是源文件。类似地,<...>
指令中 #include
的内容不需要是有效的文件名。编译器如何准确地使用命名头<...>
和"..."
是实现定义的。
关于C:翻译单元说明,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41927218/