我们在 从头学C(34) 外部变量 中将计算器的程序分割成了多个文件,这么做一方面是程序可以对 main 函数隐藏很多实现的细节,另一方面也是考虑到在实际的程序中,它们各个部分可能分别来自单独编译的库(模块化开发)。
然而我们需要在 main.c 以及 getop.c 中使用 extern 关键字对外部函数进行声明,以保证能正常调用。对简单程序来说,这个不是问题,但对于大型程序,尤其涉及到很多的源文件的时候,这种方式做起来就非常麻烦了。
所以,我们来看下头文件是如何实现在多个源文件之间实现定义和声明共享的。
第四章 函数与程序结构 >> 4.5 头文件
我们可以把共享的部分(包括函数和变量)集中起来,放在一个额外的副本(也就是头文件 *.h)中,而在其他需要使用到这些共享部分的源文件(*.c)中通过 #include 指令把这个头文件包含进来。这样只需要一个统一的头文件,既保证程序的正确性,也降低开发/修改程序的难度。
因此,我们上上节的计算器程序可以改成:
my_header.h
#define NUMBER '0' void push(double); double pop(void); int getop(char []); int getch(void); void ungetch(int);
main.c
#include <stdio.h> #include <stdlib.h> #include "my_header.h" #define MAXOP 100 main() { ... ... }
pop_push.c
#include <stdio.h> #include "my_header.h" #define MAXVAL 100 int sp = 0; double val[MAXVAL]; void push(double) { ... ... } double pop(void) { ... ... }
getop.c
#include <stdio.h> #include <ctype.h> #include "my_header.h" getop() { ... ... }
getch_ungetch.c
#include <stdio.h> #define BUFSIZE 100 char buf[BUFSIZE]; int bufp = 0; int getch(void) { ... ... } void ungetch(int) { .. ... }
其中 getch_ungetch.c 中由于没有涉及到需要共享的部分,因此没有包含该头文件。
一方面,我们希望每个文件只能访问它完成任务所需的信息,另一方面现实中维护较多的头文件是件很麻烦的事,所以我们可以得出的结论是:
- 对于简单的、不涉及到太多源文件的小程序,可以不用头文件;
- 对于中等规模的程序,最好只用一个头文件存放各部分需要共享的对象;
- 更大型的程序需要更多的头文件,我们需要恰当的组织它们,使程序结构不至于出现混乱。