在c語言中,修飾符extern用在變數或者函式的宣告前,用來說明「此變數/函式是在別處定義的,要在此處引用」。
1 基本解釋
extern可以置於變數或者
函式前,以標示變數或者
函式的定義在別的檔案中,提示編譯器遇到此變數和
函式時在其他模組中尋找其定義。另外,extern也可用來進行鏈結指定。
2. extern修飾變數的宣告。
舉例來說,如果檔案a.c需要引用b.c中變數int v,就可以在a.c中宣告extern int v,然後就可以引用變數v。這裡需要注意的是,被引用的變數v的鏈結屬性必須是外鏈結(external)的,也就是說a.c要引用到v,不只是取決於在a.c中宣告extern int v,還取決於變數v本身是能夠被引用到的。這涉及到c語言的另外乙個話題--變數的作用域。能夠被其他模組以extern修飾符引用到的變數通常是全域性變數。還有很重要的一點是,extern int v可以放在a.c中的任何地方,比如你可以在a.c中的函式fun定義的開頭處宣告extern int v,然後就可以引用到變數v了,只不過這樣只能在函式fun作用域中引用v罷了,這還是變數作用域的問題。對於這一點來說,很多人使用的時候都心存顧慮。好像extern宣告只能用於檔案作用域似的。
3. extern修飾函式宣告。
從本質上來講,變數和函式沒有區別。函式名是指向函式二進位制塊開頭處的指標。如果檔案a.c需要引用b.c中的函式,比如在b.c中原型是int fun(int mu),那麼就可以在a.c中宣告extern int fun(int mu),然後就能使用fun來做任何事情。就像變數的宣告一樣,extern int fun(int mu)可以放在a.c中任何地方,而不一定非要放在a.c的檔案作用域的範圍中。對其他模組中函式的引用,最常用的方法是包含這些函式宣告的標頭檔案。使用extern和包含標頭檔案來引用函式有什麼區別呢?extern的引用方式比包含標頭檔案要簡潔得多!extern的使用方法是直接了當的,想引用哪個函式就用extern宣告哪個函式。這大概是kiss原則的一種體現吧!這樣做的乙個明顯的好處是,會加速程式的編譯(確切的說是預處理)的過程,節省時間。在大型c程式編譯過程中,這種差異是非常明顯的。
4. 此外,extern修飾符可用於指示c或者c++函式的呼叫規範。
比如在c++中呼叫c庫函式,就需要在c++程式中用extern 「c」宣告要引用的函式。這是給鏈結器用的,告訴鏈結器在鏈結的時候用c函式規範來鏈結。主要原因是c++和c程式編譯完成後在目標**中命名規則不同。
5 問題:extern 變數
在乙個原始檔裡定義了乙個陣列:char a[6];
在另外乙個檔案裡用下列語句進行了宣告:extern char *a;
請問,這樣可以嗎?
答案與分析:
1)、不可以,程式執行時會告訴你非法訪問。原因在於,指向型別t的
指標並不等價於型別t的陣列。extern char *a宣告的是乙個
指標變數而不是字元陣列,因此與實際的定義不同,從而造成執行時非法訪問。應該將宣告改為extern char a[ ]。
2)、例子分析如下,如果a = "abcd",則外部變數a=0x61626364 (abcd的ascii碼值),*a顯然沒有意義
顯然a指向的空間(0x61626364)沒有意義,易出現非法記憶體訪問。
3)、這提示我們,在使用extern時候要嚴格對應宣告時的格式,在實際程式設計中,這樣的錯誤屢見不鮮。
4)、extern用在變數宣告中常常有這樣乙個作用,你在*.c檔案中宣告了乙個全域性的變數,這個全域性的變數如果要被引用,就放在*.h中並用extern來宣告。
6 問題:extern
函式2當函式
提供方單方面修改
函式原型時,如果使用方不知情繼續沿用原來的extern申明,這樣編譯時編譯器不會報錯。但是在執行過程中,因為少了或者多了輸入引數,往往會照成系統錯誤,這種情況應該如何解決?
答案與分析:
目前業界針對這種情況的處理沒有乙個很完美的方案,通常的做法是提供方在自己的***_pub.h中提供對外部
介面的宣告,然後呼叫方include該標頭檔案,從而省去extern這一步。以避免這種錯誤。
寶劍有雙鋒,對extern的應用,不同的場合應該選擇不同的做法。
7 問題:extern 「c」
在c++
環境下使用c
函式的時候,常常會出現編譯器無法找到obj模組中的c
函式定義,從而導致鏈結失敗的情況,應該如何解決這種情況呢?
答案與分析:
c++語言在編譯的時候為了解決
函式的多型問題,會將
函式名和引數聯合起來生成乙個中間的
函式名稱,而
c語言則不會,因此會造成鏈結時找不到對應
函式的情況,此時c
函式就需要用extern 「c」進行鏈結指定,這告訴編譯器,請保持我的名稱,不要給我生成用於鏈結的中間
函式名。
下面是乙個標準的寫法:
//在.h檔案的頭上
#ifdef __cplusplus
#if __cplusplus
extern "c"
#endif
#endif /* __cplusplus */
8 問題:extern
函式1
常常見extern放在
函式的前面成為
函式宣告的一部分,那麼,
c語言的關鍵字extern在
函式的宣告中起什麼作用?
答案與分析:
如果函式
的宣告中帶有關鍵字extern,僅僅是暗示這個
函式可能在別的原始檔裡定義,沒有其它作用。即下述兩個
函式宣告沒有明顯的區別:
extern int f(); 和int f();
當然,這樣的用處還是有的,就是在程式中取代include 「*.h」來宣告
函式,在一些複雜的專案中,我比較習慣在所有的
函式宣告前新增extern修飾。
extern用法詳解
1 基本解釋 extern可以置於變數或者函式 前,以標示變數或者函式 的定義在別的檔案中,提示編譯器遇到此變數和函式 時在其他模組中尋找其定義。另外,extern也可用來進行鏈結指定。2 問題 extern 變數 在乙個原始檔裡定義了乙個陣列 char a 6 在另外乙個檔案裡用下列語句進行了宣告...
extern用法詳解
extern可以置於變數或者函式 前,以標示變數或者函式 的定義在別的檔案中,提示編譯器遇到此變數和函式 時在其他模組中尋找其定義。另外,extern也可用來進行鏈結指定。2 問題 extern 變數 在乙個原始檔裡定義了乙個陣列 char a 6 在另外乙個檔案裡用下列語句進行了宣告 extern...
extern用法詳解
1 基本解釋 extern可以置於變數或者函式 前,以標示變數或者函式 的定義在別的檔案中,提示編譯器遇到此變數和函式 時在其他模組中尋找其定義。另外,extern也可用來進行鏈結指定。2 問題 extern 變數 在乙個原始檔裡定義了乙個陣列 char a 6 在另外乙個檔案裡用下列語句進行了宣告...