在C程序中,我看到.h文件始终使用以下方式明确包含:
#include "some_header_file.h"
另一方面,.c文件很少使用:
#include "some_c_file.c"
三个问题:
为什么有区别?
您何时会偏离常规并明确包含.c文件?
链接器如何知道项目中包含所需的.c文件以及在何处查找?
答案 0 :(得分:1)
头文件指定接口(函数声明,宏定义,类型定义等),而.c文件指定实现(函数和对象定义)。 / p>
您几乎永远不会在另一个.c文件中包含.c文件,主要是因为如果两个.c文件出于不同的目的使用相同的符号,或者如果您已将include({{1}包含a.c
,其中包含b.c
等),您最终会得到一个太大的编译器无法处理的翻译单元。这也意味着,如果更改了包含的.c文件,则无论是否更改了代码,都必须重新编译包含该文件的所有内容,这会使构建花费的时间比应花的时间更长。
编辑
第三个原因是您可能希望从较大的程序中隐藏一些数据项或功能(实际上是使这些项“专用”于特定的源文件)。如果将该源文件包含在另一个源文件中,则会失去该功能。同样,如果在不同文件中将相同的变量或函数名称用于不同的目的,这将是一个真正的问题。
END EDIT
分开编译和链接是一件好事,尤其是在大型项目上。
链接器通常对源文件一无所知-在典型的工具链中,程序员通过makefile或类似文件指定所有内容的位置。
答案 1 :(得分:0)
为什么有区别?
坚持模块化设计方法。
您何时会偏离常规并明确包含.c文件?
大多数从不。
链接器如何知道项目中包含必需的.c文件以及在何处查找?
链接器不需要.c文件,但是需要编译器(在此问题中)从.c文件创建的.o文件(例如)。这些.o文件所在的位置,链接程序由其调用方(IDE,makefile,用户)告知。
答案 2 :(得分:0)
未在其他.c文件中明确包含.c的主要原因之一是希望避免使用重复的符号。
请考虑定义全局符号(变量或函数)名称a.c
的文件A
。假设b.c
和c.c
#include文件a.c
。如果您有一个可以编译并链接b.c
和c.c
并生成应用程序的Makefile,则由于A
的重复定义,将导致链接器失败:
A A
| |
a.c a.c
| |
b.c c.c
\ /
executable
在此依赖关系图中,除非A
是文件作用域符号,否则无法构建可执行文件。
避免这种情况的方法是将所有#include
个文件.c
放在一个“主”文件中,这是一个非常严格的设计反模式。