最近寫了一段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
)
因此,咱們能夠得出結論:
extern
用於擴展變量和函數的可見性。extern
,不須要再定義和聲明的時候使用extern
。extern
時,它只是聲明沒有定義。extern
聲明而且有初始化時,和變量的定義同樣。