1. 程式人生 > >extern關鍵字詳解

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)

所以,我們可以得出結論:

  1. 宣告可以多次,定義只能一次。
  2. 關鍵字extern用於擴充套件變數和函式的可見性。
  3. 由於函式預設存在extern,不需要再定義和宣告的時候使用extern
  4. 當變數使用extern時,它只是宣告沒有定義。
  5. 當變數用extern宣告並且有初始化時,和變數的定義一樣。    出自:https://segmentfault.com/a/1190000008949574