我应该将包含文件放在头文件还是源文件中?如果头文件包含include语句,那么如果我在源文件中包含该头文件,那么我的源文件中是否将包含头文件中的所有包含文件?还是仅将它们包括在源文件中?
我应该将包含文件放在头文件还是源文件中?如果头文件包含include语句,那么如果我在源文件中包含该头文件,那么我的源文件中是否将包含头文件中的所有包含文件?还是仅将它们包括在源文件中?
Answers:
如果标题本身需要,则仅将put包含在标题中。
例子:
size_t
。然后#include <stddef.h>
在头文件中。strlen
。然后#include <string.h>
在源文件中。size_t
怎么办?
size_t
或std::string
?
多年来,对此存在很多分歧。一次,通常标头仅声明与之相关的模块中的内容,因此许多标头有特定的要求,因此您需要#include
一组标头(按特定顺序)。一些非常传统的C程序员仍然遵循此模型(至少在某些情况下是宗教上的)。
最近,正在朝着使大多数标头独立的方向发展。如果该标头需要其他内容,则标头本身会进行处理,确保包括所需的所有内容(如果存在排序问题,请以正确的顺序)。就我个人而言,我更喜欢这样做-特别是当标题的顺序很重要时,它可以解决一次问题,而不是要求使用它的每个人都可以再次解决问题。
请注意,大多数标头应仅包含声明。这意味着添加不必要的标头通常不会对最终的可执行文件产生任何影响。发生的最坏情况是它会稍微减慢编译速度。
您的#include
s应该是头文件,并且每个文件(源文件或头文件)都应该#include
是所需的头文件。头文件应该#include
是必需的最小头文件,源文件也应该,尽管它对源文件不那么重要。
源文件将具有它#include
的标头和标头#include
,依此类推,直到最大嵌套深度。这就是为什么你不想多余的#include
头文件中有 s的原因:它们可能导致源文件包含很多可能不需要的头文件,从而减慢了编译速度。
这意味着完全有可能两次包含头文件,这可能是个问题。传统方法是在头文件中放置“ include guards”,例如对于文件foo.h:
#ifndef INCLUDE_FOO_H
#define INCLUDE_FOO_H
/* everything in header goes here */
#endif
我发展到二十多年的方法是这样的;
考虑一个图书馆。
有多个C文件,一个内部H文件和一个外部H文件。C文件包括内部H文件。内部H文件包括外部H文件。
从编译器POV可以看到,它在编译C文件时有一个层次结构。
外部->内部-> C代码
这是正确的顺序,因为外部使用的是第三方使用该库所需的一切。编译C代码需要内部的代码。
在某些环境中,如果仅包含一个需要的头文件,则编译速度最快。在其他环境中,如果所有源文件都可以使用相同的主标头集合(某些文件可能在公共子集之外还具有其他标头),则将优化编译。理想情况下,应构造标头,以使多个#include操作无效。将#include语句包含在要包含的文件的include-guard的检查中可能会比较好,尽管这会导致依赖于该guard的格式。此外,根据系统的文件缓存行为,目标可能被完全#ifdef移走的不必要的#include可能不会花费很长时间。
要考虑的另一件事是,如果一个函数需要一个指向结构的指针,则可以将原型编写为
无效foo(struct BAR_s * bar);
没有定义BAR_s的范围。避免不必要的非常方便的方法包括。
PS –在我的许多项目中,都会有一个文件,期望每个模块都会包含#include文件,其中包含诸如整数大小的typedef以及一些常见的结构和联合之类的内容[例如
typedef union { unsigned long l; 无符号短lw [2]; 无符号字符磅[4]; } U_QUAD;
(是的,我知道如果我改用big-endian架构会很麻烦,但是由于我的编译器不允许在联合体中使用匿名结构,因此对联合体中的字节使用命名标识符要求将它们作为theUnion.b.b1等,这似乎很烦人。