用#include可以包含其他頭文件中變量、函數的聲明,為什么還要extern關鍵字,如果我想引用一個全局變量或函數a,我只要直接在源文件中包含#include (xxx.h包含了a的聲明)不就可以了么,為什么還要用extern呢??這個問題一直也是似是而非的困擾著我許多年了,今天上網狠狠查了一下總算小有所獲了:
比如全局變量: #ifndef _XX_頭文件.H #define _XX_頭文件.H int A; #endif 那么,很糟糕的是,這里的int A是個全局變量的定義,所以如果這個頭文件被多次引用的話,你的A會被重復定義 顯然語法上錯了。只不過有了這個#ifndef的條件編譯,所以能保證你的頭文件只被引用一次,不過也許還是會岔子,但若多個c文件包含這個頭文件時還是會出錯的,因為宏名有效范圍僅限于本c源文件,所以在這多個c文件編譯時是不會出錯的,但在鏈接時就會報錯,說你多處定義了同一個變量, extern 這個關鍵字真的比較可惡,在聲明的時候,這個extern居然可以被省略,所以會讓你搞不清楚到底是聲明還是定義,下面分變量和函數兩類來說:
(1)變量 尤其是對于變量來說。
第四個 等于 第 三個,都是定義一個可以被外部使用的全局變量,并給初值。 糊涂了吧,他們看上去可真像。但是定義只能出現在一處。
也就是說,不管是int a;還是extern int a=0;還是int a=0;都只能出現一次,而那個extern int a可以出現很多次。 當你要引用一個全局變量的時候,你就要聲明,extern int a;這時候extern不能省略,因為省略了,就變成int a;這是一個定義,不是聲明。
(2)函數 函數,函數,對于函數也一樣,也是定義和聲明,定義的時候用extern,說明這個函數是可以被外部引用的,聲明的時候用extern說明這是一個聲明。 但由于函數的定義和聲明是有區別的,定義函數要有函數體,聲明函數沒有函數體,所以函數定義和聲明時都可以將extern省略掉,反正其他文件也是知道這個函數是在其他地方定義的,所以不加extern也行。兩者如此不同,所以省略了extern也不會有問題。 比如: int fun(void) { return 0; } 很好,我們定義了一個全局函數 int fun(void); 我們對它做了個聲明,然后后面就可以用了 加不加extern都一樣 我們也可以把對fun的聲明 放在一個頭文件里,最后變成這樣 int fun(void);//函數聲明,所以省略了extern,完整些是extern int fun(void); int fun(void) { return 0; }//一個完整的全局函數定義,因為有函數體,extern同樣被省略了。 然后,一個客戶,一個要使用你的fun的客戶,把這個頭文件包含進去,ok,一個全局的聲明。沒有問題。 但是,對應的,如果是這個客戶要使用全局變量,那么要extern 某某變量;不然就成了定義了。 總結下: 對變量而言,如果你想在本源文件中使用另一個源文件的變量,就需要在使用前用extern聲明該變量,或者在頭文件中用extern聲明該變量; 對函數而言,如果你想在本源文件中使用另一個源文件的函數,就需要在使用前用聲明該變量,聲明函數加不加extern都沒關系,所以在頭文件中函數可以不用加extern。
(5) 模塊的.c文件中別忘包含自己的.h文件