c h和 cpp在編譯中的作用

2022-09-16 21:39:29 字數 2215 閱讀 8789

首先,我們可以將所有東西都放在乙個.cpp檔案內.然後編譯器就將這個.cpp編譯成.obj,obj是什麼東西?就是編譯單元了.

乙個程式,可以由乙個編譯單元組成,也可以有多個編譯單元組成. 如果你不想讓你的源**變得很難閱讀的話,就請使用多個編譯單元吧.(乙個函式不能放到兩個編譯單元裡面,但兩個以上就可以分別放在乙個單元,也就是cpp裡面)那麼就是乙個.cpp對應乙個.obj,然後將所有的obj鏈結起來(通過乙個叫鏈結器的程式),組成乙個.exe,也就是程式了.

如果乙個.cpp要用到另乙個.cpp定義的函式怎麼辦? 只需在這個.cpp種寫上他的函式宣告就可以了.其餘工作由鏈結器幫你完成,你可以隨便呼叫該函式.鏈結器將所有的obj連線起來,但是如果碰巧有相同的函式或外部變數怎麼辦?他如何識別?一般來說是不能允許在同乙個程式中,出現兩個一樣的函式名或外部變數名.但是只得慶幸的是,c++可以通過一種叫做鏈結屬性的關鍵字來限定,你這個函式是屬於整個程式公用的,還是只是在乙個編譯單元obj裡面使用的.這些關鍵字就是extern 和static;extern是外部鏈結的意思,也就是除了這個單元,外部的單元也是能夠訪問這個函式的.static 是內部鏈結,自屬於自己單元.說了這麼久,還沒有說.h的作用呢?其實沒有.h也能很好的工作,但是當你發現乙個外部鏈結的函式或外部變數,需要許多份宣告,因為c++這種語言,在使用函式和變數的時候,必須將他宣告,為何要宣告?宣告之後才知道他的規格,才能更好的發現不和規格的部分.你別妄想乙個編譯單元,會自動從另乙個編譯單元那裡得到什麼資訊,知道你是如何定義這個函式的.所以說,只要使用到該函式的單元,就必須寫乙份宣告在那個.cpp裡面,這樣是不是很麻煩,而且,如果要修改,就必須乙個乙個修改.這真讓人受不了..h就是為了解決這個問題而誕生,他包含了這些公共的東西.然後所有需要使用該函式的.cpp,只需要用#include包含進去便可.以後需要修改,也只是修改乙份內容.請注意不要濫用.h,.h裡面不要寫**,.h不是.cpp的倉庫,什麼都塞到裡面.如果在裡面寫**,當其他.cpp包含他的時候,就會出現重複定義的情況,比如將函式func();放到標頭檔案a.h,裡面還有一些a.cpp需要的宣告等;然後你發現b.cpp需要用到a.cpp裡面的乙個函式,就很高興的將a.h包含進來.注意,#include並不是什麼申請指令,他就是將指定的檔案的內容,原封不動的拷貝進來.這時候實際上a.cpp和b.cpp都有乙個func()函式的定義.如果這個函式是內部鏈結static的話,還好,浪費了一倍空間;如果是extern,外部鏈結(這個是預設情況),那麼根據在同乙個程式內不可出現同名函式的要求,聯結器會毫不留情給你乙個連線錯誤!;如果你還不太理解.那麼就嘗試不用h,只用多個cpp看看應該如何寫.嘗試在兩個cpp中寫同名函式.看看是否鏈結出錯.嘗試在cpp使用其他cpp定義的函式.看看應該如何做.

個人認為:

.cpp內用於(1)函式實現(包括全域性函式(預設)、靜態函式)。

(2)全域性變數、靜態變數定義。

(3)靜態函式宣告,靜態變數宣告。(指定編譯單元內部使用的函式和變數)

.h內用於(1)全域性函式宣告,注意靜態函式不包括在內。

(2)全域性變數宣告,無靜態變數。

我的一點總結 by ordedere

上文說到,#include並不是什麼申請指令,他就是將指定的檔案的內容,原封不動的拷貝進來。所以我們可以將.h的**連線到.cpp的前端,從而可以更加清晰的看到:

a.h, b.cpp & c.cpp 都同時include了a.h,那麼b.cpp其實可以看做是檔案:a.h+b.cpp連線而成的cpp原始碼;而a.h+c.cpp連線成的原始碼等價於c.cpp include a.h。

那麼對於變數在.h中的宣告,對cpp有如下情況的分類:

在.h中宣告變數int a,等價於在.cpp的前端宣告(或者定義)變數全域性變數int a;

在.h中宣告外部變數extern int a; 等價於在.cpp 的前端宣告了外部變數a;所以這個變數a被指明在其他cpp檔案中定義;

在.h中宣告全域性變數 static int a; 等價於在所有包含.h的cpp中將有檔案內部的變數a,且每個include該**件的cpp中的a變數的位址是不同的,也就是原作者說道的空間浪費問題。

同理,對於函式的宣告:

在.h 中宣告靜態(static)函式,就相當於在所包含該標頭檔案的cpp程式中需要定義該靜態函式;

在.h中宣告外部(extern)函式,即指明該函式的定義是在其他原始檔中。

在.h中宣告普通函式,即在cpp的開始部分宣告乙個函式是乙個道理。

所以:靜態函式和全域性靜態變數的宣告應該在cpp中(畢竟靜態的意義就是確保該函式或者變數的作用空間僅限於該原始檔內部),而避免在.h中有靜態變數或函式的宣告。

c h和 cpp在編譯中的作用

首先,我們可以將所有東西都放在乙個.cpp檔案內.然後編譯器就將這個.cpp編譯成.obj,obj是什麼東西?就是編譯單元了.乙個程式,可以由乙個編譯單元組成,也可以有多個編譯單元組成.如果你不想讓你的源 變得很難閱讀的話,就請使用多個編譯單元吧.乙個函式不能放到兩個編譯單元裡面,但兩個以上就可以分...

陣列和指標在編譯的時候的區別

c語言中指標和陣列在編譯時的區別 例如 int a 10 和int b,a 5 和 b 5 在編譯的時候區別是什麼?經過反覆的查資料和請教他人,最後在 c專家程式設計 裡找到了很好的答案。1。編譯器對陣列名和指標變數的處理方式 編譯器在編譯時會產生乙個符號表,記錄了符號名和它的位址。對於指標變數,這...

C C 在編譯的過程中動態指定巨集

在日常的軟體程式設計中,軟體的版本往往根據使用物件的不同而編譯出不同的版本。一種很實用的編譯方法 在編譯的過程中指定巨集,例如 gcc def.c define vip 檔名 def.c 在命令中指定巨集 gcc c define 巨集名稱 include int main 使用 gcc def.c...