以下摘录自《Linux C 程序设计大全》。
对于小型代码而言,可以将所有的文件书写在一个源文件中。但是如果代码量很大,这种组织代码的形式就不适合了。那么应当怎样组织多个文件,多个模块的大型代码呢?
首先,应当将所有需要使用的函数分类。具体就是将功能相同的函数写在同一个文件内,在C语言中,一个文件即代表一个模块。例如,对于一个链表操作的程序而言,插入链表节点的操作函数和删除链表节点的操作函数操作的是同一个资源(链表),完成操作类似(都需要修改链表)。
其次,如果模块中的函数是一个函数接口,需要被其他模块所引用,则应当定义为外部函数。如果函数仅在模块内使用,则应当定义为static函数(相当于Java中私有函数)。这样做可以防止各个模块中的函数因为重名现象而出现的错误。使用static关键字定义函数之后,只有本模块的函数可以对其进行调用。同理,仅在模块内使用的全局变量也应当定义为static。需要被其他模块引用的全局变量则应当使用默认方式定义。
最后,定义一个common.h头文件,该头文件中包括以下内容:
(1)头文件区:包含所有模块共同需要的头文件,例如常用的stdio.h,stdlib.h,unistd.h文件等。
(2)全局宏区:包含所有模块公用的宏定义,例如调试开关,一些缓冲区的大小等。
(3)全局变量区:包含所有非static全局变量的声明。
(4)函数接口区:包含所有模块的函数接口。
有了该common.h头文件后,各个模块的文件只要包含该头文件,就可以应用函数接口和全局变量,包含需要的头文件和宏定义。
下面是一个经过组织的链表处理程序的代码。首先是common.h,该文件包含了所有的头文件,宏定义,全局变量的声明和函数接口的声明。
/* 头文件区 */ #include <stdio.h> #include <stdlib.h> /* 全局定义区,该程序没有用到宏,声明了一个结构体 */ typedef struct node * Node; /* 自定义节点指针类型 */ /* 链表节点结构 */ struct node { int var; Node next; }; /* 全局变量声明区 ,注意是声明不是定义 */ extern Node head; /* 函数接口声明区 */ extern int insert(int var); extern int del(int var, Node * res); extern void print(); extern void destory();
list.c文件定义所有操作链表的函数,该文件中没有用到static函数,所有的函数均作为接口提供给其他模块使用:
#include "common.h" Node head; /* 链表头 */ /* 插入节点函数 */ int insert(int var) { // 省略具体代码实现 } /* 删除节点函数 */ int del(int var, Node * res) { //省略具体代码实现 } /* 遍历链表:打印每个节点 */ void print() { // ... } /* 遍历链表,释放每个节点 */ void destory() { // .... }
main.c文件定义main函数,该函数书写程序的执行流程:
#include "common.h" int main() { //具体是实现省略 return 0; }
调试开关:在调试程序时免不了需要输出一些当前程序执行的信息。当调试完毕之后,需要将这些输出信息去掉,这时可以使用C语言提供的条件编译的技术,将这些输出信息定义为宏。