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