<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

        多文件EXTERN 變量和函數

        作者:huqin   來源:本站原創   點擊數:  更新時間:2014年08月15日   【字體:

        用#include可以包含其他頭文件中變量、函數的聲明,為什么還要extern關鍵字,如果我想引用一個全局變量或函數a,我只要直接在源文件中包含#include (xxx.h包含了a的聲明)不就可以了么,為什么還要用extern呢??這個問題一直也是似是而非的困擾著我許多年了,今天上網狠狠查了一下總算小有所獲了:

         頭文件  首先說下頭文件,其實頭文件對計算機而言沒什么作用,她只是在預編譯時在#include的地方展開一下,沒別的意義了,其實頭文件主要是給別人看的。  我做過一個實驗,將頭文件的后綴改成xxx.txt,然后在引用該頭文件的地方用 #include"xxx.txt"  編譯,鏈接都很順利的過去了,由此可知,頭文件僅僅為閱讀代碼作用,沒其他的作用了!  不管是C還是C++,你把你的函數,變量或者結構體,類啥的放在你的.c或者.cpp文件里。然后編譯成lib,dll,obj,.o等等,然后別人用的時候 最基本的gcc hisfile.cpp yourfile.o|obj|dll|lib 等等。 但對于我們程序員而言,他們怎么知道你的lib,dll...里面到底有什么東西?要看你的頭文件。你的頭文件就是對用戶的說明。函數,參數,各種各樣的接口的說明。     那既然是說明,那么頭文件里面放的自然就是關于函數,變量,類的“聲明”了。記著,是“聲明”,不是“定義”。 那么,我假設大家知道聲明和定義的區別。所以,最好不要傻嘻嘻的在頭文件里定義什么東西。
        比如全局變量: #ifndef _XX_頭文件.H #define _XX_頭文件.H int A; #endif  那么,很糟糕的是,這里的int A是個全局變量的定義,所以如果這個頭文件被多次引用的話,你的A會被重復定義 顯然語法上錯了。只不過有了這個#ifndef的條件編譯,所以能保證你的頭文件只被引用一次,不過也許還是會岔子,但若多個c文件包含這個頭文件時還是會出錯的,因為宏名有效范圍僅限于本c源文件,所以在這多個c文件編譯時是不會出錯的,但在鏈接時就會報錯,說你多處定義了同一個變量,    extern 這個關鍵字真的比較可惡,在聲明的時候,這個extern居然可以被省略,所以會讓你搞不清楚到底是聲明還是定義,下面分變量和函數兩類來說: 
        (1)變量  尤其是對于變量來說。
         extern int a;//聲明一個全局變量a
         int a; //定義一個全局變量a 
         extern int a =0 ;//定義一個全局變量a 并給初值。
         nt a =0;//定義一個全局變量a,并給初值, 
        第四個 等于 第 三個,都是定義一個可以被外部使用的全局變量,并給初值。 糊涂了吧,他們看上去可真像。但是定義只能出現在一處。
        也就是說,不管是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。 
           (1) 處理時間:文件包含也是以"#"開頭來寫的(#include ), 那么它就是寫給預處理器來看了, 也就是說文件包含是會在編譯預處理階段進行處理的。 
          (2) 處理方法:在預處理階段,系統自動對#include命令進行處理,具體做法是:降包含文件的內容復制到包含語句(#include )處,得到新的文件,然后再對這個新的文件進行編譯。  舉個很實際的例子,在單片機、ARM或其他嵌入式開發中,每一個平臺可能本身都有多種不同的硬件模塊,使用時需要去寫相應的驅動程序,這樣就可以把各個硬件模塊的驅動程序作為一個模塊(比如lcd驅動對對應lcd.c和lcd.h,IIC驅動對應I2C.c和I2C.h等),當具體使用到某個模塊時,只需要在將對應的.c和.h文件添加進工程,并在文件中包含對就的.h文件即可。  
         所以關于頭文件的寫法個人總結以下幾點:
         (1) 對應的.c文件中寫變量、函數的定義
         (2) 對應的.h文件中寫變量、函數的聲明
         (3) 如果有數據類型的定義 和 宏定義 ,請寫的頭文件(.h)中
         (4) 頭文件中一定加上#ifndef...#define....#endif之類的防止重包含的語句
        (5) 模塊的.c文件中別忘包含自己的.h文件
        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮