程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 【編程好習慣】精確包含頭文件

【編程好習慣】精確包含頭文件

編輯:關於C語言

請注意這裡用的是“精確”而不是“正確”,之所以不說正確,那是因為如果頭文件沒有被正確地包含的話,編譯器是不會生成最終的目標代碼的。那用精確一詞想表達除正確之外的什麼意思呢?包含兩層意思。

第一層意思是,只包含必需的頭文件。圖1是一個簡單的示例程序,先讓我們假設這個文件只有foo()一個函數的實現,在foo()函數中也只有簡單的一行打印語句。我們知道printf()函數的原型聲明來源於標准庫的stdio.h頭文件,foo.c文件中除了包含stdio.h外還包含了另外一個多余的頭文件 —— time.h,從實現的角度來看沒有問題。但是當一個項目很大的時候,這種類似的行為會突顯出編譯效率低下這一問題。當foo.c文件在被編譯時,第一步要做的是預處理,預處理的最終結果可以看作是將stdio.h和time.h中的內容全部放到foo.c文件中,當然,如果stdio.h和time.h中又包含其它的頭文件的話,它們也都全部會被放入到最終的foo.c文件中,圖2示例了采用GCC的-E選項所獲得的最終預處理完的文件final.c,從圖中可以看出,本來是7行的文件變成了1419行,這意味著什麼?意味著如果多包含頭文件則編譯所花費的時間將更長。因為,編譯器在最終分析final.c文件中的詞法和語法時,它必須從頭到尾一行一行的處理。千萬別小看對於每一個文件多出來的那麼一點點時間,當一個項目有幾十萬行代碼時,所多出來的時間就不可小視了。往往當這種現象成為了一個不可忽視的問題時,要消除它所需付出的努力已經很大了,甚至是項目組不可承受的。另外,這種糾正行為大多是“體力勞動”。

foo.c
#include <stdio.h>
#include <time.h>

void foo ()
{
   printf ("Just for an example!\n");
}
圖1
yunli.blog.51cto.com~
$ gcc -E foo.c >final.c

yunli.blog.51cto.com~
$ vi final.c
1414 # 3 "foo.c" 2
1415
1416 void foo ()
1417 {
1418     printf ("Just for a test!\n");
1419 }
:set nu
圖2

第二層意思就是,盡可能不要在頭文件中包含其它的頭文件,取而代之的是盡量在.c源文件中包含它們。對於圖3和圖4兩種實現方式,光從foo()函數的角度來說是一模一樣的,只是對於stdio.h頭文件的包含一個是放在foo.h中的,而另一個則是放在foo.c中的。大部分情形下設計一個模塊的目的是需要供其它的模塊使用,而其它的模塊在需要使用foo()函數時通常需要包含foo.h頭文件。采用圖3的實現方式將造成包含foo.h頭文件則會導致間接地包含stdio.h,進而出現前面所講的編譯速度下降這一問題,而圖4的實現就不存在這一問題。想想,printf()函數只是在foo()函數的實現中需要被使用,而完全可以不讓foo.h頭文件知道這一信息,所以跟本就沒有必要在foo.h頭文件中包含stdio.h。

foo.h
#include <stdio.h>

void foo ();
foo.c
#include “foo.h”

void foo ()
{
   printf ("Just for an example!\n");
}

圖3
foo.h
void foo ();
foo.c
#include <stdio.h>
#include “foo.h”

void foo ()
{
   printf ("Just for an example!\n");
}
圖3

   相信不少讀者有這種類似的項目經驗,即為了包含頭文件省事,在項目進展的過程中定義一個包羅萬象的公共頭文件,然後讓其它的源程序文件只需包含這一個頭文件就行了,從而省去在創建一個新源程序時考慮哪些要包含、哪些不用包含這一過程。看完這則編程好習慣後,相信讀者會明白那並不是一種好的實踐。

本文出自 “至簡李雲” 博客,請務必保留此出處http://yunli.blog.51cto.com/831344/275313

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved