以前自己大学就上了一门谭浩强的C语言课,没好好学,其实是老师没引导好! 因为当时对C语言中很多概念不懂,老师也不能给我解释到本质上! 老谭的书也不怎么样! 就带着各种疑问晃到了大三! 后来自己专业(电子信息工程)有电子制作,接触了51单片机才慢慢捡起了C语言!但也只是皮毛!说实话当时就是简单的逻辑控制,while for ,swich 语句,指针没怎么用,结构(structure)没怎么用,更别谈结构的妙用了! 不过好在最后用 状态机原理写了个按键检测程序,可以高效率地检测到任何时长的按键动作,一下子被程序和算法所折服!
后来,……菜鸟不断的遇到各种问题! 先不扯远了 !今天我们来剖析一下头文件。
以下均为个人见解。
我们把 a.c 这样的文件叫source file, 把 a.h 叫做该source file 对应的 header file。
很久很久以前没有头文件,别的source file 想要引用 a.c 里面定义的函数的话,就得要 声明,
extern func();
但是万一后来又用到更多的函数呢,又得 增加声明,
extern func1();
extern func2();
这很麻烦,于是就诞生了头文件,a.c 里希望别人用的函数的声明全部放到a.h 这个header file 里了。 别人想用a.c 里的函数,只要包含a.h 就行了!
那a.c 需要包含自己的header file a.h 吗? 目前不用,因为头文件的作用就是声明,a.c 里的文件只要在使用前定义就不必要声明,因为定义本身也同时是声明。当然a.c 里面有main 函数,而且func()函数的引用先于定义,那就得包含自己的头文件a.h ,以起到声明作用。
另外,如果函数入参里有些结构类型也必须一同让别人知道,于是就把这些结构类型定义在a.h 文件里了(定义类型不占用内存哦),那a.c 就不用自己再定义这些类型了,只要包含一下a.h 就行了!
至此,头文件的作用就是,声明一些供别的模块(source file ,编译单元)使用的函数类型和数据类型等,那到底哪些该放到header file 里声明呢:就是那些 source file 和 别的source file 共用的类型和函数,只要不是共用的,就不要放到 hearer file 里。
另外如果file_3.c 依赖于file_1.h 和 file_2.h 两个头文件,但是file_1.h 里本身就包含了file_2.h 头文件,那么file_3.c 仅仅需要包含file_1.h就行了,还是说要把file_1.h和file_2.h都包含进来!This is a question which should be concerned !其实原则就是包含逻辑要清晰。 这里面又有点抽象层的概念。
1. 假如file_3.c 里面独自依赖file_2.h,这种依赖和file_1.h没任何关系,那么file_3.c 除了包含file_1.h外,还要专门包含一下file_2.h,即使file_1.h 里已经包含了file_2.h,这就叫包含逻辑清晰。
2. 假如,file_3.c 里对file_2.h 的依赖是由 对file_1.h 的依赖引入的,那么,人家file_1.h 都已经把file_2.h 抽象到自己的file_1.h 了,你file_3.c 就不要再操心人家file_1.h 和file_2.h 之间的依赖关系了! 因此,file_3.c 不包含file_2.h 在逻辑上也是清晰的,因为file_3.c 本质上仅依赖file_1.h ,就不必再包含file_2.h 了,不知道有没有说清楚! ~呵呵
另外,一些C语言库头文件,为了表示对C++友好,都会在前面 加入 extern “C",这样C++包含了C的头文件,就能直接调用C的函数了! 如下:
#ifdef __cplusplus
extern "C" {
#endif
/* function declaration */
#ifdef __cplusplus
}
#endif
头文件尽量不要乱包含,至于为什么,每个人都应该有自己的思考和答案!
This is it !