extern的作用
1、修飾變數的宣告
舉例來說,如果檔案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中的函式func定義的開頭處宣告extern int v,然後就可以引用到變數v了,只不過這樣只能在函式func作用域中引用v罷了,這還是變數作用域的問題。對於這一點來說,很多人使用的時候都心存顧慮,好像extern宣告只能用於檔案作用域似的。在編譯階段,雖然a.c中找不到變數v的定義,但不會出錯,因為extern修飾符告訴編譯器該變數定義在了其他模組,它會在連結時在b.c模組中找到該變數。
2、修飾函式的宣告
從本質上來說,變數和函式沒有區別。函式名是指向函式二進位制塊開頭處的指標。如果檔案a.c需要引用b.c中的函式,比如在b.c中原型是int func(int mu),那麼就可以在a.c中宣告extern int func(int mu),然後就能使用func來做任何事情。就像變數的宣告一樣,extern int func(int mu)可以放在a.c中任何地方,而不定非要放在a.c的檔案作用域的範圍中。對其他模組中函式的引用,最常使用的方法是包含這些函式宣告的標頭檔案。使用extern和包含標頭檔案來引用函式有什麼區別呢?extern的引用方式是直接了當的,可以選擇性的引用,這樣做的一個明顯的好處是,會加速程式的預處理過程,因為沒有了#include的擴充套件時間。而包含標頭檔案是比較簡潔乾淨省事的做法,這樣的好處是包含以後,標頭檔案裡所有的宣告都可以使用了,不用一個一個使用extern來聲明瞭,節省編碼量。
有一點值得注意,全域性變數的宣告和定義,如果不加extern是無法區別的,比如int v,既是宣告又是定義,預設值為0。所以如果只是宣告,一定要用extern修飾,extern int v是宣告,可以出現多次;int v是定義,只能出現一次。而函式的宣告和定義是顯而易見的,宣告沒有函式體,定義必須要有函式體,所以extern int func(int mu),和int func(int mu)是等價的,函式的宣告有沒有extern修飾都是可以的。
3、用於指示C或者C++函式的呼叫規範。比如在C++中呼叫c庫函式,就需要在C++程式中用extern "c"宣告要引用的函式。這是給連結器用的,告訴連結器在連結的時候用c函式規範來連結。主要原因是C++支援函式的過載,對於函式名的命名規則和C不一樣。