前段時間看了extern 的用法,今天試了一下出現了如下問題,我在一個標頭檔1中定義了全域常量,然後在標頭檔2中定義了同樣的全域變數,然後把兩個標頭檔包含在另外一個cpp裡面出現了了重新定義的錯誤,去迴轉檔案2中的全域定義,undeclared identifier 的錯誤。最後把2中的所有全域變數加上了extern,結果出現undeclared indentifier錯誤,後經過尋找在標頭檔2中沒有包含標頭檔1,修改後程式正常。
通過這個錯誤更深刻理解了extern的作用。
在編譯階段,完成對原始碼的語法檢查;在串連階段,完成空間內容的指定,比如確定函數在可執行程式中的位置。 聲明是告訴編譯器該變數或函數是存在的,定義則是分配了空間。現代編譯器一般採用按檔案編譯的方式,因此在編譯時間,各個檔案中定義的全域變數是互相透明的,也就是說,在編譯時間,全域變數的可見域限制在檔案內部。但是到了連結階段,要將各個檔案的內容“合為一體”,因此,如果某些檔案中定義的全域變數名相同的話,在這個時候就會出現重複定義的錯誤。因此,各個檔案中定義的全域變數名不可相同。
在連結階段,各個檔案的內容(實際是編譯產生的obj檔案)是被合并到一起的,因而,定義於某檔案內的全域變數,在連結完成後,它的可見範圍被擴大到了整個程式。這樣一來,一個檔案中定義的全域變數,可以在整個程式的任何地方被使用。但會出現undeclared identifier 的錯誤。這是因為,檔案中定義的全域變數的可見度擴充到整個程式是在連結完成之後,而在編譯階段,他們的可見度仍局限於各自的檔案。
但是C++提供了一個檔案中定義的全域變數,在另外一個檔案中使用的方法,即藉助於關鍵字extern。其使用如下: extern 類型 變數名。這樣就可以在另外一個檔案中使用該檔案中定義的全域變數。最後不要忘記了加上最初定義全域變數的標頭檔。
此外,可能遇到extern “C”的用法,如下:
在C++環境下使用C函數的時候,常常會出現編譯器無法找到obj模組中的C函數定義,從而導致連結失敗的情況C++語言在編譯的時候為瞭解決函數的多態問題,會將函數名和參數聯合起來產生一個中間的函數名稱,而C語言則不會,因此會造成連結時找不到對應函數的情況,此時C函數就需要用extern “C”進行連結指定,這告訴編譯器,請保持我的名稱,不要給我產生用於連結的中間函數名。