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