結合我本身的經驗,談一談模塊化編程時#include應該出現的位置。總結起來大致有二條規則:編程
1、規則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中。當一個項目的代碼量很大時,因爲效率地下而多佔用的時間就沒法忽視了。spa
2、規則2:使#include出如今它被須要的地方code
爲了使用printf()函數,能夠把#include<stdio.h>放在foo.h文件中,編譯也能夠正常經過,以下:blog
===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中,定義了以下結構體定義:io
=====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文件中是必須的!
用一句話歸納:只在必要的地方包含必要的頭文件!