组织C源文件的好方法?

时间:2009-08-11 23:12:09

标签: c

我总是组织我的C源的方法是将结构,宏和函数原型放在头文件和.c文件中的函数实现中。但是,我最近一直在阅读大量项目的其他人的代码,我开始看到人们经常在C源本身中定义诸如结构和宏之类的东西,紧接在使用它的函数之上。我可以看到一些好处,因为你不必去寻找特定函数使用的结构和宏的定义,一切都在与使用它的函数大致相同的地方。但是我也可以看到它的一些缺点,因为它意味着没有一个用于结构/宏定义的中央存储库,因为它们分散在源代码中。

我的问题是,决定何时将宏/结构定义放在C源代码中而不是头文件本身有什么好的经验法则?

7 个答案:

答案 0 :(得分:29)

通常,您放在头文件中的所有内容都是接口的一部分,而您放在源文件中的所有内容都是实现的一部分。

也就是说,如果头文件中的某些内容仅被关联的源文件使用,则它是移动到该源文件的绝佳选择。这样可以防止“污染”每个使用标头的文件的名称空间,以及它们从未打算使用的宏和类型。

答案 1 :(得分:12)

Interfaces and implementations就是它的全部内容。

接受答案的附录:在标题中放置不完整的结构声明可能很有用,但只将定义放在.c文件中。现在,指向该结构的指针为您提供了一个完全控制的私有类型。非常有用,可以保证关注点的分离;有点像C ++中的私有成员。

有关大量示例,请点击链接。

答案 2 :(得分:8)

将您的公共结构和界面放入.h文件中。

将您的私有位放入.c文件中。

如果我有多个实现逻辑功能集的.c文件,我会将需要在这些实现文件中共享的内容放入*p.h文件中('p'表示私有) 。客户端代码不应包含* p.h标头。

例如,如果我有一组实现XML解析器的例程,我可能会有以下组织:

xmlparser.h    - the public structures, types, enums, and function prototypes

xmlparserp.h   - private types, function prototypes, etc. that client code 
                 doesn't and shouldn't need

xmlparser.c    - implementation of the XML parser
xmlutil.c      - some other implementation bits (would include xmlparserp.h)

答案 3 :(得分:6)

  • 定义模块外部接口的东西放在标题中。
  • 模块中使用的东西应保留在C文件中。
  • 头文件应包含支持其声明所需的标头
  • 标题应将自己包装在#ifndef NAME_H中,以确保每个编译单元包含一个
  • 模块应包含自己的标题以确保一致性

很多人不知道这个基本的东西BTW,这是在任何规模的C项目上保持理智所必需的。

答案 4 :(得分:4)

主要是,手头的问题是一种封装考虑因素。您可以将模块的头文件看作不是它的“开销”,这就是您现在正在做的事情,就像它的公共接口声明一样,这可能是您正在查看的代码正在看到它的人。

从那里开始,头文件中的内容自然是其他模块需要了解的内容:您期望在外部使用的函数的原型,用于接口目的的结构和宏,外部变量声明等等,而对于模块内部使用严格的事情则放在.c文件中。

答案 5 :(得分:4)

在David Straker的“C风格:标准和指南”(可在线提供here)一书中,对文件布局以及C文件和标题之间的划分有一些好的想法。

您可以阅读chapter 7,特别是第7.4章。

正如John Calsbeek所说,你可以根据你的组织如何使用标题部分。 如果一个结构,类型,宏,......仅由一个源使用,则可以在那里移动代码。

你可能有原型的头文件和一些常用声明的头文件(类型定义等等)

答案 6 :(得分:2)

如果在.c中定义结构和宏,则无法从其他.c文件中使用它

要这样做,你必须将它放在.h中,以便#include告诉编译器在哪里检查你的结构和宏

除非你#include“x.c”,你不应该这样做=)