C語言頭文件的看法

1 術語

1.1 定義與聲明

定義:建立存儲空間。聲明:不需要建立存儲空間,僅僅是爲了擴展該變量的作用範圍而作的“聲明”。

定義只能有一次,但聲明可以很多。如int Num爲定義,而extern Num或extern int Num則爲聲明。

1.2 變量的分類

l  作用域來分:局部變量與全局變量

 

l  生存期來分:靜態存儲方式(分配固定的存儲空間)與動態存儲方式(根據需要進行動態的分配),具體有4種:自動的auto,靜態的static,寄存器的register,外部的extern。

n  auto變量如果沒有特別聲明是static,則默認的變量都是auto

n  static 用static聲明局部變量:在函數調用結束後其值不消失,而保留原值,即其佔用的存儲單元不釋放。(在編譯時賦初值,即只賦初值一次,在程序運行時它已有初值)(雖然靜態局部變量在函數調用結束後仍然存在,但其他函數是不能引用它的)

n  用static聲明外部變量 變量只限於本文件引用,而不能被其他文件引用

 

1.3 內部函數與外部函數

內部函數又稱靜態函數:只能被本文件中其他函數所調用。定義內部函數時,在前面添加static。

外部函數:定義時添加關鍵字extern,在定義時省略extern,則隱含爲外部函數。在需要調用此函數的文件中,用extern對函數作聲明,表示該函數是在其他文件中定義的外部函數。

 

1.4 作用域

 

2 編譯器的工作過程

  簡單的說其實要理解C文件與頭文件(即.h)有什麼不同之處,首先需要弄明白編譯器的工作過程,一般說來編譯器會做以下幾個過程:

 

  1.預處理階段

 

  2.詞法與語法分析階段

 

  3.編譯階段,首先編譯成純彙編語句,再將之彙編成跟CPU相關的二進制碼,生成各個目標文件 (.obj文件)

 

  4.連接階段,將各個目標文件中的各段代碼進行絕對地址定位,生成跟特定平臺相關的可執行文件,當然,最後還可以用objcopy生成純二進制碼,也就是去掉了文件格式信息。(生成.exe文件)

 

編譯器在編譯時是以C文件爲單位進行的,也就是說如果你的項目中一個C文件都沒有,那麼你的項目將無法編譯,連接器是以目標文件爲單位,它將一個或多個目標文件進行函數與變量的重定位,生成最終的可執行文件,在PC上的程序開發,一般都有一個main函數,這是各個編譯器的約定,當然,你如果自己寫連接器腳本的話,可以不用main函數作爲程序入口!

 

(main .c文件 目標文件 可執行文件)

2.1 頭文件如何來關聯源文件?

  這個問題實際上是說,已知頭文件"a.h"聲明瞭一系列函數(僅有函數原型,沒有函數實現),"b.cpp"中實現了這些函數,那麼如果我想在"c.cpp"中使用"a.h"中聲明的這些在"b.cpp"中實現的函數,通常都是在"c.cpp"中使用#include "a.h",那麼c.cpp是怎樣找到b.cpp中的實現呢?

 

  其實.cpp和.h文件名稱沒有任何直接關係,很多編譯器都可以接受其他擴展名。

 

  譚浩強老師的《C程序設計》一書中提到,編譯器預處理時,要對#include命令進行"文件包含處理":將headfile.h的全部內容複製到#include "headfile.h"。這也正說明了,爲什麼很多編譯器並不care到底這個文件的後綴名是什麼----因爲#include預處理就是完成了一個"複製並插入代碼"的工作。

 

  程序編譯的時候,並不會去找b.cpp文件中的函數實現,只有在link的時候才進行這個工作。我們在b.cpp或c.cpp中用#include "a.h"實際上是引入相關聲明,使得編譯可以通過,程序並不關心實現是在哪裏,是怎麼實現的。源文件編譯後成生了目標文件(.o.obj文件),目標文件中,這些函數和變量就視作一個個符號。link的時候,需要在makefile裏面說明需要連接哪個.o.obj文件(在這裏是b.cpp生成的.o.obj文件),此時,連接器會去這個.o.obj文件中找在b.cpp中實現的函數,再把他們buildmakefile中指定的那個可以執行文件中

 

3 頭文件的作用

頭文件可以定義所用的函數列表,方便查閱你可以調用的函數;

頭文件可以定義很多宏定義,就是一些全局靜態變量的定義,在這樣的情況下,只要修改頭文件的內容,程序就可以做相應的修改,不用親自跑到繁瑣的代碼內去搜索。

頭文件只是聲明,不佔內存空間,要知道其執行過程,要看你頭文件所申明的函數是在哪個.c文件裏定義的,才知道。

頭文件並不是C自帶的,可以不用。

調用了頭文件,就等於賦予了調用某些函數的權限,如果你要算一個數的N次方,就要調用Pow()函數,而這個函數是定義在math.c裏面的,要用這個函數,就必需調用math.h這個頭文件。

4 頭文件的一般規則

a.宏定義(預處理#define);

b.結構、聯合和枚舉聲明;

c.typedef聲明;(typedef long doubleREAL;)

d.外部函數聲明;

e.全局變量聲明;

5 實際應用

l 定義宏常量或宏公式的時候,一定要加圓括號

l 頭文件只聲明不定義

C語言中一個人爲的規範:.h文件中聲明的函數,如果在其對應的.c文件中有定義,那麼我們在聲明這個函數時,不使用extern修飾符如果反之,則必須顯示使用extern修飾符(即在不同的.h文件中,聲明該函數,要添加extern). 可以用extern Num,而不是非要extern char Num。

l  不能把實際的代碼(如函數體)或全局變量定義(即定義和初始化實例)放入頭文件中。

l  不要試圖用#include把你的源文件“鏈接”成一個整體。#include是用來引入頭文件而不是.c文件的。

l 如果定義或聲明爲一個源文件私有則最好留在該文件中。(作用域限於單文件的私有函數和變量應該聲明爲static。)

l  當聲明或定義需要在多個文件中共享時,把他們放入一個頭文件中尤其重要。不要在兩個或多個源文件的頂部重複聲明或定義宏。應該把它們放入一個頭文件中,然後在需要的時候用#include包含進來。這樣做的原因並不僅僅是減少打字輸入——這樣可以保證在聲明或定義變化的時候,只需要修改一處即可將結果一致地傳播到各個源文件。(特別是,永遠不要把外部函數原型放到.c文件中。參見2.)

l  當希望在多個源文件中共享變量或函數時,需要確保定義和聲明的一致性。最好的安排是在某個相關的.c文件中定義,然後再頭.h文件中進行外部聲明,在需要使用的時候,只要包含對應的頭文件即可。定義變量的.c文件也應該包含該頭文件,以便編譯器檢查定義的和聲明的一致性。

l  定義一個Globel_Var.C文件來放全局變量,然後在與之相對應的Globel_Var.H文件中來聲明全局變量

l  防止被重複包含。

使用下面的宏防止一個頭文件被重複包含。

#ifndef MY_INCLUDE_H

#define MY_INCLUDE_H

<頭文件內容>

#endif

l 說明性頭文件

還有一種頭文件,說明性頭文件,這種頭文件不需要有一個對應的代碼文件,在這種文件裏大多包含了大量的宏定義,沒有暴露的數據變量和函數。這些文件給出以下建議:

1,包含一些需要的概念性的東西.

2,命名方式,定義的功能.h

3,不包含任何其他的頭文件.

4,不定義任何類型.

5,不包含任何數據和函數聲明.

6 引用

http://blog.csdn.net/janders/article/details/611081

C語言頭文件的使用

 

http://blog.csdn.net/ts_54eagle/article/details/4418627

C語言的變量作用域及頭文件

 

http://www.cnblogs.com/webcyz/archive/2012/09/16/2688035.html

C語言頭文件的作用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章