C语言模块化编程中的头文件
前面我们在演示多文件编程时创建了 main.c 和 module.c 两个源文件,并在 module.c 中定义了一个函数和一个全局变量,然后在 main.c 中进行了声明。
不过实际开发中很少这样做,
- 一般是将函数和变量的声明放到头文件,
- 再在当前源文件中 #include 进来。
- 如果变量的值是固定的,最好使用宏来代替。
下面的例子是改进后的代码。
main.c 源码:
#include <stdio.h> #include "module.h" int main(){ printf("a = %d\n", a); func(); printf("OS: %s\n", OS); return 0; }
module.c 源码:
#include <stdio.h> int a = 100; void func(){ printf("www.baidu.com\n"); }
module.h 源码:
#define OS "Windows 7" extern int a; extern void func();
- 在 Visual Studio 中,将上面的文件全部添加到工程,点击“运行(Run)”就可以看到输出结果。
- 在 GCC 中,使用下面的命令来编译和运行:
$gcc main.c module.c $./a.out
- .c和.h文件都是源文件,除了后缀不一样便于区分外和管理外,其他的都是相同的,在.c中编写的代码同样也可以写在.h中,包括函数定义、变量定义、预处理等。
- 但是,.h 和 .c 在项目中承担的角色不一样:
- .c 文件主要负责实现,也就是定义函数和变量;
- .h 文件主要负责声明(包括变量声明和函数声明)、宏定义、类型定义等。
这些不是C语法规定的内容,而是约定成俗的规范,或者说是长期形成的事实标准。
根据这份规范,头文件可以包含如下的内容:
- 可以声明函数,但不可以定义函数。
- 可以声明变量,但不可以定义变量。
- 可以定义宏,包括带参的宏和不带参的宏。
- 结构体的定义、自定义数据类型一般也放在头文件中。
在项目开发中,我们可以将一组相关的变量和函数定义在一个 .c 文件中,并用一个同名的 .h 文件(头文件)进行声明,其他模块如果需要使用某个变量或函数,那么引入这个头文件就可以。
这样做的另外一个好处是可以保护版权,我们在发布相关模块之前,
- 可以将它们都编译成目标文件,
- 或者打包成静态库,
- 只要向用户提供头文件,用户就可以将这些模块链接到自己的程序中。