模塊化編程時,#include到底要放在哪里?


結合我自己的經驗,談一談模塊化編程時#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文件中是必須的!

 

用一句話概括:只在必要的地方包含必要的頭文件!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM