結合我自己的經驗,談一談模塊化編程時#include應該出現的位置。總結起來大體有二條規則:
一、規則1:只包含必要的頭文件
看下面這個模塊:
===foo.c====
#include <stdio.h>
#include <foo.h>
#include <uart.h>
void foo () { printf ("hello world!\n"); }
===foo.h==== #ifndef __foo_h__ #define __foo_h__ extern void foo(); #endif
在foo()函數中也只有簡單的一行打印語句。由於printf()函數的原型聲明來源於stdio.h,因此foo.c中包含了stdio.h無可厚非,否則根本無法使用。但foo.c文件中除了包含stdio.h外還包含了另外一個多余的頭文件 ——uart.h,這不會導致編譯的出錯,但我們並不需要使用uart.h中聲明的接口,因此這種行為會導致編譯效率的降低。如果此時uart.h中還包含了其它文件,那么全部都會在預處理時展開到foo.c中。當一個項目的代碼量很大時,由於效率地下而多占用的時間就無法忽視了。
二、規則2:使#include出現在它被需要的地方
為了使用printf()函數,可以把#include<stdio.h>放在foo.h文件中,編譯也可以正常通過,如下:
===foo.h==== #ifndef __foo_h__ #define __foo_h__ #include <stdio.h> extern void foo(); #endif
===foo.c==== #include <foo.h> void foo () { printf ("hello world!\n"); }
但這樣會產生一個問題,stdio.h對於我們的頭文件foo.h來說,是必須的么?當然不是!那么會導致什么樣的問題呢?我們已經直到.h文件的作用相當於模塊的使用說明書,如果其它模塊要使用foo模塊時,需要通過#include<foo.h>來添加接口函數,此時就會間接的包含了stdio.h,同樣的會導編譯致速度下降的問題。因此,正確的做法是將#include<stdio.h>放在foo.c中,如下:
===foo.h==== #ifndef __foo_h__ #define __foo_h__ extern void foo(); #endif ===foo.c==== #include <stdio.h> #include <foo.h> void foo () { printf ("hello world!\n"); }
理解了上面的例子,則看下面一條實例:
在system.h中,定義了如下結構體定義:
=====system.h===== #ifndef __system_h__ #def __system_h__ typedef struct stuTAG{ char * name; u8 age; }stu_st; #endif
同樣在一個foo.c模塊中,定義了一個函數:
===foo.h==== #ifndef __foo_h__ #define __foo_h__ #include "system.h" extern void print_info(stu_st * student); #endif
=====foo.c===== #include "foo.h" #include <stdio.h> void print_info(stu_st * student) { printf("name:%s\n",student->name); printf("age :%d\n",student->age); }
從這個foo模塊的實現代碼來看,foo.h和foo.c都需要了解stu_st結構體的內容,也就是stu_st是被foo.c和foo.h同時需要的,因此它必須被放置在foo.h中,否則編譯時會出現stu_st未定義的錯誤,此時將#include放置在.h文件中是必須的!
用一句話概括:只在必要的地方包含必要的頭文件!
