首先,我們可以將所有東西都放在乙個.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生成.obj.但是.cpp裡面有#include將指定標頭檔案(其實任何檔案都行)插進來,組成完整的. cpp.假如你不喜愛這個方式,你也可以直接在.cpp裡面寫好了,而不放到.h裡面,載用指令拷貝進來.標頭檔案是工具,但不是必須.
編譯的時候,並不會去找b.cpp檔案中的函式實現,只有在link的時候才進行這個工作。我們在b.cpp或c.cpp中用#include 「a.h」實際上是引入相關宣告,使得編譯可以通過,程式並不關心實現是在**,是怎麼實現的。原始檔編譯後成生了目標檔案(.o或.obj檔案),目標檔案中,這些函式和變數就視作乙個個符號。在link的時候,需要在makefile裡面說明需要連線哪個.o或.obj檔案(在這裡是b.cpp生成的.o或.obj檔案),此時,聯結器會去這個.o或.obj檔案中找在b.cpp中實現的函式,再把他們build到makefile中指定的那個可以執行檔案中。
在unix下,甚至可以不在原始檔中包括標頭檔案,只需要在makefile中指名即可(不過這樣大大降低了程式可讀性,是個不好的習慣哦^_^)。在vc中,一幫情況下不需要自己寫makefile,只需要將需要的檔案都包括在project中,vc會自動幫你把makefile寫好。
通常,編譯器會在每個.o或.obj檔案中都去找一下所需要的符號,而不是只在某個檔案中找或者說找到乙個就不找了。因此,假如在幾個不同檔案中實現了同乙個函式,或者定義了同乙個全域性變數,鏈結的時候就會提示「redefined」。
編譯原理 預編譯 編譯 彙編與鏈結
我們編寫的程式 是怎樣執行起來的?到底執行的是什麼內容?平時我們所說的編譯主要包括預編譯 編譯 彙編與鏈結,這四部分分別都幹什麼工作,主要職能有哪些。講述編譯之前,我們先要了解程式記憶體。乙個由c c 編譯的程式占用的記憶體,大致分為以下幾個部分 1 棧區 stack 由編譯器自動分配釋放 存放函式...
鏈結 裝載與庫 編譯與鏈結 編譯器做了什麼
編譯過程一般分為6步 掃瞄 詞法分析 語法分析 語義分析 源 優化 生成和目標 優化,每個過程所做的事情及輸出總結如下 步驟做的事情或輸出 掃瞄 詞法分析 將源 的字串行分割成一系列記號 語法分析 對記號進行語法分析,產生語法樹 語義分析 編譯期間用的是靜態語義分析,對語法樹的表示式標記型別 源 優...
C語言編譯與鏈結
預處理過程主要處理那些源 檔案只能夠的以 開始的預編譯指令。比如 include define 等,主要處理規則如下 1 將所有的 define 刪除,並且展開所有的巨集定義 2 處理所有條件預編譯指令,比如 if ifdef elif else endif 3 處理 include 預編譯指令,將...