包含语句,标题或来源的位置?

我应该把包括在头文件或源文件? 如果头文件包含include语句,那么如果我在源文件中包含头文件,那么我的源文件是否包含了所有包含在头文件中的文件? 或者我应该只将它们包含在我的源文件中?

如果标题本身需要它们,则只包含在标题中。

例子:

  • 你的函数返回size_ttypes。 然后在文件中#include <stddef.h>
  • 你的函数使用strlen 。 然后在文件中包含#include <string.h>

这些年来一直有很多不同意见。 有一段时间,传统的头只是声明与它相关的模块中的东西,所以很多头文件都有特定的要求,所以你需要包含一些特定的头文件(以特定的顺序)。 一些非常传统的C程序员仍然遵循这个模式(至less在某些情况下,宗教上)。

最近,大多数标题都是独立的。 如果这个头文件需要别的东西,那么头文件本身会处理这个头文件,确保它包含了所需要的东西(按照正确的顺序,如果有顺序问题的话)。 就我个人而言,我更喜欢这一点 – 特别是当头文件的顺序很重要时,它可以一次解决问题,而不是要求所有使用它的人再次解决问题。

请注意,大多数标题只能包含声明。 这意味着添加一个不必要的标题不应该(通常)对最终的可执行文件有任何影响。 发生的最糟糕的情况是它会减慢编译速度。

你的#include应该是头文件,并且每个文件(源头或头文件)都应该包含它所需要的头文件。 头文件应该包含必要的最小头文件,源文件也应该包含,尽pipe对于源文件来说不是那么重要。

源文件将包含头文件#include s,头文件#include ,等等,直到最大的嵌套深度。 这就是为什么你不想在头文件中包含多余的#include :它们会导致源文件包含很多不需要的头文件,从而减慢了编译速度。

这意味着头文件可能包含两次,这可能是一个问题。 传统的方法是在头文件中join“包含卫兵”,如foo.h文件:

 #ifndef INCLUDE_FOO_H #define INCLUDE_FOO_H /* everything in header goes here */ #endif 

如果头文件A #includes头文件B和C,则包含A的每个源文件也将得到B和C #included 。 预处理器实际上只是执行文本replace:在任何地方,它find说#include <foo.h>的文本,将其replace为foo.h文件的文本。

你是否应该把#includes放在头文件或源文件中有不同的意见。 就个人而言,我更喜欢将所有#includes放在源文件中,但是如果没有其他必要的头文件,那么任何不能编译的头文件都应该包含这些头文件。

并且每个头文件都应该包含一个包含防止被多次包含的内容。

使所有的文件,使他们可以使用只包含他们包括。 如果你不需要在你的头包含删除它。 在一个大项目中,如果你没有遵守这个规范,那么当有人从一个被这个文件的使用者所使用的头文件中,甚至是头文件中删除一个头文件的时候,你都会打开整个构build。

在某些环境下,如果只包含需要的头文件,编译速度会最快。 在其他环境中,如果所有源文件都可以使用相同的主标头集合(某些文件可能具有超出公共子集的额外标头),则编译将进行优化。 理想情况下,头文件应该被构造,所以多个#include操作将不起作用。 围绕#include语句来检查要包含的文件的include-guard可能是件好事,尽pipe这会对该守卫的格式造成依赖。 而且,根据系统的文件caching行为,一个不必要的#include可能不会花费很长时间。

另一件需要考虑的事情是,如果一个函数需要一个指向结构体的指针,那么可以把原型写成

 void foo(struct BAR_s * bar);

没有定义BAR_s必须在范围内。 避免不必要的一个非常方便的方法包括。

PS – 在我的许多项目中,会有一个文件,期望每个模块都会包含#include,包含整数大小的typedefs和一些常见的结构和联合[例如

 typedef union {
   unsigned long l;
   unsigned short lw [2];
   unsigned char lb [4];
 } U_QUAD;

(是的,我知道如果我转向一个大端架构,会遇到麻烦,但由于我的编译器不允许工会使用匿名结构,因此在联合中使用命名标识符来访问联盟.b.b1等,这似乎相当烦人。

我已经演变成二十多年的方法是这样的;

考虑一个图书馆。

有多个C文件,一个内部H文件和一个外部H文件。 C文件包含内部H文件。 内部H文件包含外部H文件。

从编译器的POV中可以看到,编译C文件时,有一个层次结构;

外部 – >内部 – > C代码

这是正确的sorting,因为这是外部的是第三方需要使用库的一切。 编译C代码需要内部的内容。

如果将源文件放在标题中,则源文件将包含include语句。 但是,在某些情况下,最好将它们放在源文件中。

请记住,如果您在其他来源中包含该标题,那么它们也将从标题中获取包含,这并不总是可取的。 你应该只包括它使用的地方。

你只能在头文件中包含你需要声明常量和函数声明的文件。 从技术上讲,这些内容也将包含在你的源文件中,但是为了清楚起见,你应该只在每个文件中包含你实际需要使用的文件。 你也应该从多重包含中保护你的标题:

 #ifndef NAME_OF_HEADER_H #define NAME_OF_HEADER_H ...definition of header file... #endif 

这可以防止头被多次包含,导致编译器错误。