从“精确包含头文件”(参见《精确包含头文件》)这一编程好习惯中能够获得另一个好习惯,那就是就是尽量保证模块的对外头文件简浩。
一般的编程习惯是将全部的数据结构都放在头文件中,且这个头文件也包含模块接口函数的原型声明,图1就是一个例子。请注意其中的62~69行所定义的bucket_t结构,这一结构是模块的内部数据结构,也就是说从模块的外部来看根本不知道这一结构的存在,这从76~83行模块全部函数的原型声明中能够看出,由于这些函数的参数和返回类型中都没有引用它。
编程
timer.h
00037: typedef struct tag_timer *timer_handler_t;
00038:
00039: // callback function for timer expiration
00040: typedef error_t (*expiration_cb_t)(timer_handler_t _handler, void *_arg);
00049:
00050: typedef struct tag_timer
00051: {
00052: ...
00060: } timer_instance_t;
00061:
00062: typedef struct
00063: {
00064: ...
00069: } bucket_t;
00070:
00076: int timer_lock_init ();
00077: void timer_fire ();
00078: error_t timer_alloc (timer_handler_t *_p_handler,
00079: msecond_t _duration,expiration_cb_t _cb, const char *_name);
00080: error_t timer_free (timer_handler_t _handler);
00081: error_t timer_start (timer_handler_t _handler, void *_arg);
00082: error_t timer_stop (timer_handler_t _handler);
00083: void timer_dump ();
图1
bucket_t结构的定义放在timer.h头文件中合适吗?从简化模块头文件的角度来讲是不合适的,由于外部在使用定时器模块时并不须要使用到bucket_t结构,所以应当将它从timer.h中移出去。有两种作法,一是将这一结构放入到timer.c文件中,或者定义一个只用来被timer.c包含的模块私有头文件。当内部数据结构只须要被一个.c文件引用时,前一种方式更简单,这能够省去新增长一个文件的麻烦;可是,当有多个.c文件须要使用它时则第二种方法更合适。
简化模块头文件的目的就是为了让其它模块的.c文件在包含它时,能够作到所需编译的文件大小最小化,从而提升程序的编译效率,其缘由在“精确包含头文件”这一编程发习惯中有所阐述。
数据结构