理解C語言中的關鍵字extern

最近寫了一段C程序,編譯時出現變量重複定義的錯誤,本身查看沒發現錯誤。使用Google發現,本身對 extern理解不透徹,我搜到了這篇文章,寫得不錯。我拙劣的翻譯了一下。(原文: http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/)

  我肯定這篇文章對c語言的初學者會有很大的幫助,由於這將使他們更好更熟練的使用c語言。因此就讓我先來講說extern關鍵字在變量和函數上的應用。最基本的extern關鍵字擴展了變量和函數的可見度。這可能就是它爲何命名爲extern的緣由。函數

幾乎全部人都知道聲明和定義變量(函數)的意義,可是爲了這篇文章的完整性,我想弄清楚它們。聲明一個變量(函數)只是代表這個變量(函數)存在於程序的某個地方,並無爲它們分配內存。可是,聲明變量(函數)具備重要做用,那就是說明變量(函數)的類型。所以,當一個變量聲明,程序知道變量的類型,在函數聲明的狀況下,程序知道函數的參數和返回類型。這就是所謂的聲明。來到定義,當咱們定義一個變量(函數),除了聲明的做用,它也爲該變量(函數)分配內存。所以,咱們能夠認爲聲明是定義的子集。從上面的說明,顯而易見,變量(函數)能夠聲明屢次,只能定義一次。翻譯

如今回到咱們的主要目標:理解C語言中的關鍵字extern。我已經解釋過聲明定義的做用了,由於咱們必須藉助它們來理解關鍵字extern。咱們先來了解一種簡單的狀況,extern對函數的做用。默認狀況下,聲明和定義一個函數,都有一個extern的前綴,這意味着在聲明和定義函數時,前面不寫extern,它也是默認存在的。例以下面的代碼。code

int foo(int arg1, char arg2);

聲明的函數前面沒有extern,但編譯器會在前面加上關鍵字extern,以下內存

extern int foo(int arg1, char arg2);

定義函數的狀況和上面同樣(函數的定義是指帶有函數體)。所以,每當咱們定義一個函數的時候,前面總會有默認的關鍵字extern。因爲聲明能夠屢次重複,定義只能完成一次,咱們能夠看到一個函數的聲明能夠在多個C/H文件或單個的C/H文件中重複屢次。可是該函數實際只定義了一次(僅在一個文件中)。這樣的函數在整個程序中都是可見的,任何文件任何地方均可以調用。(經過函數的聲明,編譯器在編譯時就知道函數定義在哪裏)。編譯器

第二種狀況,extern對變量的做用。如何聲明一個變量而不定義它?這是一個理解extern對變量做用的重要問題,答案以下:it

extern int var;

在上面,一個整型變量var被聲明(沒有定義,沒有分配內存)。而且,根據須要,咱們能夠聲明屢次。編譯

如今,如何定義一個變量?答案以下:class

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聲明而且有初始化時,和變量的定義同樣。
相關文章
相關標籤/搜索