extern關鍵字詳解
我確定這篇文章對c語言的初學者會有很大的幫助,因為這將使他們更好更熟練的使用c語言。所以就讓我先來說說extern
關鍵字在變數和函式上的應用。最基本的extern
關鍵字擴充套件了變數和函式的可見度。這可能就是它為什麼命名為extern
的原因。
幾乎所有人都知道宣告和定義變數(函式)的意義,但是為了這篇文章的完整性,我想弄清楚它們。宣告
一個變數(函式)只是表明這個變數(函式)存在於程式的某個地方,並沒有為它們分配記憶體。但是,宣告變數(函式)具有重要作用,那就是說明變數(函式)的型別。因此,當一個變數宣告,程式知道變數的型別,在函式宣告的情況下,程式知道函式的引數和返回型別。這就是所謂的宣告。來到定義
現在回到我們的主要目標:理解C語言中的關鍵字extern
。我已經解釋過宣告
和定義
的作用了,因為我們必須藉助它們來理解關鍵字extern
。我們先來了解一種簡單的情況,extern
對函式的作用。預設情況下,宣告和定義一個函式,都有一個extern
的字首,這意味著在宣告和定義函式時,前面不寫extern
,它也是預設存在的。例如下面的程式碼。
int foo(int arg1, char arg2);
宣告的函式前面沒有extern
extern
,如下
extern int foo(int arg1, char arg2);
定義函式的情況和上面一樣(函式的定義是指帶有函式體)。因此,每當我們定義一個函式的時候,前面總會有預設的關鍵字extern
。由於宣告可以多次重複,定義只能完成一次,我們可以看到一個函式的宣告可以在多個C/H檔案或單個的C/H檔案中重複多次。但是該函式實際只定義了一次(僅在一個檔案中
)。這樣的函式在整個程式中都是可見的,任何檔案任何地方都可以呼叫。(通過函式的宣告,編譯器在編譯時就知道函式定義在哪裡)。
第二種情況,extern
對變數的作用。如何宣告一個變數而不定義它?這是一個理解extern
extern int var;
在上面,一個整型變數var
被宣告(沒有定義,沒有分配記憶體)。並且,根據需要,我們可以宣告多次。
現在,如何定義一個變數?答案如下:
int var;
在這裡,宣告及定義了一個整型變數var
(宣告是定義的子集,定義一個變數就包含了宣告),這裡還為變數var
分配了記憶體。現在,讓我們感到驚訝的是,當我們定義或宣告一個函式時,前面會有預設的extern
,但對於變數的情況就不一樣了。如果變數也和函式一樣,那麼它們永遠不會分配記憶體,它們僅僅被宣告。因此,當我們想要宣告而不定義一個變數就需要加上關鍵字extern
。此外extern
將變數的能見度延伸到了整個程式,我們知道變數宣告和定義的地方,可以在整個程式的任何地方使用它們。下面藉助幾個例子來理解extern
int var;
int main(void)
{
var = 10;
return 0;
}
分析:程式編譯成功,var
是一個全域性變數(隱勢宣告)
extern int var;
int main(void)
{
return 0;
}
分析:程式編譯成功,這裡var
只被宣告,其他地方沒有使用var
,所以沒問題。
extern int var;
int main(void)
{
var = 10;
return 0;
}
分析:程式編譯錯誤,由於聲明瞭變數var
,而沒有在其他地方定義,從本質上講,沒有為var
分配記憶體,程式又要給它賦值。
#include "somefile.h"
extern int var;
int main(void)
{
var = 10;
return 0;
}
分析:如果檔案somefile.h
檔案中有定義變數var
, 程式將會編譯成功。
extern int var = 0;
int main(void)
{
var = 10;
return 0;
}
分析:猜猜上面的程式碼能否編譯成功?在這裡按照C的標準是可以編譯通過的。宣告一個變數並給它初始化一個值,則該變數的記憶體將被分配,即該變數被定義。(有的編譯器會報告一個警告:warning: 'extern' variable has an initializer
)
所以,我們可以得出結論:
- 宣告可以多次,定義只能一次。
- 關鍵字
extern
用於擴充套件變數和函式的可見性。 - 由於函式預設存在
extern
,不需要再定義和宣告的時候使用extern
。 - 當變數使用
extern
時,它只是宣告沒有定義。 - 當變數用
extern
宣告並且有初始化時,和變數的定義一樣。 出自:https://segmentfault.com/a/1190000008949574