我不太明白应该如何在C的源文件和头文件中分隔。我经常看到许多项目有两组具有相同名称的文件(没有表示源文件和头文件的扩展名)。
到目前为止,由于缺乏理解,当我编写库时,我已经将所有类和类方法代码放入一个文件中,并且选择文件扩展名时犹豫不决。
标题中应包含哪些内容以及源文件中应包含哪些内容?我该如何实现这种分离?
答案 0 :(得分:60)
没有技术的区别。如果您愿意,编译器很乐意让您包含.c
文件或直接编译.h
文件。
然而,存在巨大的文化差异:
声明(原型)进入.h
个文件。 .h
文件是相应.c
文件中实现的接口。
定义进入.c
个文件。他们实现 .h
文件中指定的接口。
不同之处在于.h
文件可以(并且通常会)#include
进入多个编译单元(.c
文件)。如果在.h
文件中定义一个函数,它将以多个.o
文件结束,并且链接器会抱怨多重定义的符号。这就是定义不应该放在.h
文件中的原因。 (内联函数是例外。)
如果在.c
文件中定义了一个函数,并且您想要从其他.c
文件中使用它,则需要在其他.c
中提供该函数的声明。 }文件。这就是为什么你把声明放在.h
和#include
中的原因。您还可以在每个.c
文件中重复声明,但这会导致大量代码重复和无法更替的混乱。
如果在.c
文件中定义了一个函数,但不想要从其他.c
文件中使用它,则无需在其中声明它头。它本质上是.c
文件的实现细节。在这种情况下,也要创建函数static
,这样它就不会与其他文件中具有相同名称的函数冲突。
答案 1 :(得分:14)
标题中应包含哪些内容以及源文件中应包含哪些内容?
通常标头包含以下一项或多项:
struct
,union
等。)另一方面,源文件有:
如何实现这种分离?
One Definition Rule是您的朋友。
请记住,如果您正在编写库,那么这就是您的客户可以看到的内容。因此,请提供帮助,并提供可供他们使用您的图书馆的所有信息。源文件通常以二进制形式编译和提供。
顺便说一下,C没有类的概念。
答案 2 :(得分:2)
通常,头文件包含声明,源文件包含代码。
因此,如果在源文件A.c
中需要在源文件B.c
中实现的函数,则只需包含B.h
即可获得其声明。
答案 3 :(得分:1)
.c和.h文件之间几乎没有根本区别(尽管有些编译器可能会拒绝编译原始的.h文件)。差别更多的是按惯例。
通常.h文件提供API,而.c提供实现。
因此.h文件只包含其他源文件访问.c文件提供的工具所需的内容。因此.h文件将提供全局函数的函数原型,全局变量的声明(如果你真的必须拥有它们),以及它们使用的结构和其他类型。 (如果API只需要指向结构的指针,则不要公开结构。)
.h文件中也经常包含内联函数,但某些编码指南更喜欢使用单独的扩展名(例如.inl)
所有其他函数实现,变量的定义和初始化以及本地(静态)变量和函数的声明都将在.c文件中。