從extern說開去(一)

2021-07-12 02:51:09 字數 1014 閱讀 2217

extern符號的主要目的是為了實現c++對c程式的正確呼叫,在c++中完美相容c。

包含的含義主要有兩個方面:

(1)extern關鍵字表明函式和全域性變數的作用範圍。從鏈結的角度看,意味著在編譯期間會以約定的方式表示引用的在其他模組中宣告的函式或變數,等到鏈結時再重定位,進行位址修正(絕對位址修正和相對位址修正)。與之相對應的是static,用static宣告後的函式和變數無法被其他模組引用。

(2)遇到由extern宣告的部分,c++編譯器會以c的方式進行編譯。

逐條來看具體含義。

首先要搞清楚,我們通常所說的編譯並不準確。從源**到可執行檔案,要經歷4個主要步驟預編譯 -> 編譯 -> 彙編 -> 鏈結。

首先看看鏈結(因為相對簡單)。

鏈結的本質是把多個不同的目標檔案互相粘合在一起。編譯器編譯源**後生成的檔案叫做目標檔案,從廣義上看目標檔案與可執行檔案的結構是一致的,區別在於由於沒有經過鏈結的過程,引用的不是在本模組內定義的函式和全域性變數只能以約定的方式表示,並不能獲得實際的內容。以hello world程式舉例

#includeint main()

上述**中,呼叫了printf函式。函式名就是乙個指標,指向代表函式**片段的入口位址。而函式的**片段在哪呢?或者說函式名這個指標指向**呢?答案就是函式定義的模組。也就是說,對於乙個完整的可執行檔案,printf指向這個函式**片段的位置,也就是指向定義這個函式的模組的某乙個位置。而在鏈結之前,編譯的過程中這個值會以約定的方式代替,鏈結的作用就是將具體的位址填入。

搞清了鏈結的作用,我們就可以知道,對於乙個目標檔案,它所用的符號(函式和變數統稱為符號),如果是在它內部定義的(也就是在源**中定義),它可以直接獲取到這個符號的位址,即時不鏈結也可以直接用。而對於在其他檔案內定義的符號(它所引用的,比如printf),只有在鏈結之後才能獲得具體位址。

既然有可以被其他模組引用的符號(鏈結之後獲得位址的符號),那麼自然也就有不可以被其他模組所引用的符號(static宣告)。

這就是extern的第乙個含義。

從PDF說開去

最近想研究一下pdf。pdf從ps脫胎而來,秉承ps強大的描述能力,以其精美的 效果,已幾乎成為internet時代的 標準文件格式 說pdf是 標準 可能有人不愛聽,見後文 如果軟體能夠支援自動輸出 匯出 為pdf格式文件,無疑軟體的專業化色彩會更濃一些。人之常理 你推出一種文件格式,使用的人 軟...

從時間說開去

非常羨慕那種需要很少睡眠,思維敏捷,做事雷厲風行的人。之所以羨慕,是因為我不具備。我做為乙個需要很多睡眠並且睡眠質量不高的人,做事也一般是三思而後行,遇事也慢人半拍,對於我這樣乙個人,怎樣合理安排時間就成了很大的問題。從小就喜歡利用一大片的時間,專注的去做一件事情。所以,在上了大學以後,看到我的同學...

從「盜版」說開去

發行了幾年的共享軟體 vb原始碼之友 終於被盜版了,雖然共享軟體沒有給我帶來讓人羨慕的財富,但是這幾年來也有不少的正版使用者群在默默的支援著我繼續推出我的軟體產品。我的心情其實很複雜,但卻沒有憤怒,在我腦中揮之不去的卻是 盜火 英雄普羅公尺修斯的偉大形象。想想看,如果不是盜版,作為普通的個人使用者,...