C++中extern關鍵字使用

chapter 1 . extern關鍵字的作用  

  extern是一個關鍵字,它告訴編譯器存在着一個變量或者一個函數,如果在當前編譯語句的前面中沒有找到相應的變量或者函數,也會在當前文件的後面或者其它文件中定義,來看下面的例子。

   

[cpp] view plain copy
  1. // extern.cpp : Defines the entry point for the console application.  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include <iostream>  
  6. using namespace std;  
  7.   
  8. extern int i;  
  9. extern void func();  
  10. int _tmain(int argc, _TCHAR* argv[])//typedef wchar_t     _TCHAR;#define _tmain      wmain  
  11. {  
  12.     i = 0;  
  13.     func();  
  14.     return 0;  
  15. }  
  16.   
  17. int i;  
  18.   
  19. void func()  
  20. {  
  21.     i++;  
  22.     cout << "i = " << i << endl;  
  23. }  

 

    上面代碼中變量i和函數func在文件末尾定義,所以變量需要使用extern關鍵字告訴編譯器,變量在別的地方定義。extern int i我原來以爲extern i就可以,結果編譯器報錯,仔細想下確實應該,否則編譯器不知道i是什麼類型的數據,又怎麼能判斷i = 0是否是一個正確的賦值語句呢?

 

    那麼定義在其他文件中的函數和變量,如何通過extern關鍵字調用呢?

    首先,定義在其它文件中的函數和變量,可以使用兩種方法調用:

        一、使用頭文件調用,這時候,函數和變量必須在頭文件中定義和聲明。

        二、使用extern關鍵字調用,這時候函數和變量在.cpp或者.c文件中定義和聲明。

    看下面兩個例子:

    devVar.cpp函數中定義:

       

[cpp] view plain copy
  1. #include "stdafx.h"  
  2.   
  3. int i;  


 

    extern.cpp中

[cpp] view plain copy
  1. // extern.cpp : Defines the entry point for the console application.  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include <iostream>  
  6. using namespace std;  
  7.   
  8. extern int i;  
  9. extern void func();  
  10. int _tmain(int argc, _TCHAR* argv[])//typedef wchar_t     _TCHAR;#define _tmain      wmain  
  11. {  
  12.     i = 0;  
  13.     func();  
  14.     return 0;  
  15. }  
  16.   
  17. void func()  
  18. {  
  19.     i++;  
  20.     cout << "i = " << i << endl;  
  21. }  


 

   編譯工程,程序輸出:i = 1,這裏使用extern關鍵字聲明在其它cpp文件中定義的變量和函數。

 

    #include <filensme> --- 將filename文件中的內容插入到新的文件中。

    deVar.h文件中代碼爲

[cpp] view plain copy
  1. #include <stdio.h>  
  2.   
  3. int i = 1;  
  4.   
  5. void func()  
  6. {  
  7.     printf("%d",i++);  
  8. }  

     函數func修改全局變量i的值並輸出。

    extern.cpp文件內容爲:

[cpp] view plain copy
  1. #include "stdafx.h"  
  2. #include <stdio.h>  
  3. #include <iostream>  
  4. using namespace std;  
  5. #include "devVar.h"  
  6. //extern int i;  
  7. //extern void func();  
  8.   
  9. int main(void)  
  10. {  
  11.     for (int x = 0;x < 10; x++)  
  12.     {  
  13.         func();  
  14.     }  
  15. }  

程序輸出1,2,3,4,5,6,7,8,9,10,這裏#include <filname.h> 包含定義在其它頭文件中的函數和變量,在來看一個例子。

   

[cpp] view plain copy
  1. // extern.cpp : Defines the entry point for the console application.  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include <iostream>  
  6. using namespace std;  
  7.   
  8. extern int i;  
  9. extern int  func(int);//這裏extern必需的,函數定義在其它cpp文件中  
[cpp] view plain copy
  1. int _tmain(int argc, _TCHAR* argv[])//typedef wchar_t     _TCHAR;#define _tmain      wmain  
  2. {  
  3.     i = 100;  
  4.     func(i);  
  5.     return 0;  
  6. }  

    devVar.cpp文件中內容爲:

   

[cpp] view plain copy
  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. using namespace std;  
  4.   
  5. int i;  
  6.   
  7. int func(int a)  
  8. {  
  9.     i = a;  
  10.     cout << "i = " << i << endl;  
  11.     return 0;  
  12. }  


    這樣,同樣是輸出了i= 100。

    能夠使用extern引用其它cpp文件中定義的函數說明了一個問題:

    如果一個工程現編譯cpp文件,在把多個目標文件鏈接成爲可執行文件,而兩個或多個文件中,定義了相同的全局變量,那麼,程序編譯的時候不會報錯,因爲編譯器單獨編譯每個文件,在鏈接可執行文件的時候,由於多個目標文件中含有相同的全局變量,而生成可執行文件的時候,任何文件中定義的全局變量對其它目標文件都是可見的,此時由於變量定義衝突而發生錯誤。看下面的代碼:

   

[cpp] view plain copy
  1. // extern.cpp : Defines the entry point for the console application.  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include <iostream>  
  6. using namespace std;  
  7.   
  8. int i;  
  9. extern int  func(int);//這裏extern是必須的函數定義在別的cpp文件中  
  10. int _tmain(int argc, _TCHAR* argv[])//typedef wchar_t     _TCHAR;#define _tmain      wmain  
  11. {  
  12.     i = 100;  
  13.     func(i);  
  14.     return 0;  
  15. }  


 

devVar.cpp文件中,內容爲:

[cpp] view plain copy
  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. using namespace std;  
  4.   
  5. int i;  
  6.   
  7. int func(int a)  
  8. {  
  9.     i = a;  
  10.     cout << "i = " << i << endl;  
  11.     return 0;  
  12. }  

    單獨compile任何一個cpp文件都是對的,但是 編譯工程,生成可執行文件的時候報錯:

    1>LINK : D:\vctest\extern\Debug\extern.exe not found or not built by the last incremental link; performing full link
1>devVar.obj : error LNK2005: "int i" (?i@@3HA) already defined in extern.obj
1>D:\vctest\extern\Debug\extern.exe : fatal error LNK1169: one or more multiply defined symbols found

    原因是:兩個.cpp文件中都定義了全局變量i,變量重複定義了。

 

    PS:定義在.h文件中的函數和變量不能使用extern變量聲明,原因是#include <filename>在預編譯的時候將.h文件中的內容插入了cpp文件中,因此編譯器找得到在其它.h文件中定義的變量或者函數。編譯的時候,只編譯cpp文件的內容,.h文件時不參與編譯,如果使用extern聲明在.h文件中定義的變量或者函數,那麼聲明爲extern的變量和函數在其它.cpp文件中找不到,因此程序編譯的時候就發生了錯誤。

 

 

chapter2,如何混合編譯C語言和C++

    實際開發過程中,C++中會調用C與語言編寫的代碼,我在網絡上面找到一篇寫得很好的文章

   http://blog.csdn.net/keensword/article/details/401114

   就着上面的例子,我使用C語言採用兩種方法重寫了一下。

   方法一、全局函數和變量在devVar.c文件中實現,在extern.cpp文件中使用extern關鍵字聲明在devVar.c文件中定義的函數和變量。

   devVar.c文件的代碼如下所示:

   

[cpp] view plain copy
  1. #include <stdio.h>  
  2.   
  3. int i = 1;  
  4.   
  5. void func()  
  6. {  
  7.     printf("%d",i++);  
  8. }  

   extern.cpp文件中代碼如下所示:

   

[cpp] view plain copy
  1. #include "stdafx.h"  
  2. #include <stdio.h>  
  3. #include <iostream>  
  4. using namespace std;  
  5. //#include "devVar.h"  
  6. //extern int i;  
  7. //extern void func();  
  8.   
  9. extern "C"  
  10. {  
  11.     extern int i;  
  12.     extern void func();  
  13.     //#include "devVar.h"   
  14. }  
  15. int main(void)  
  16. {  
  17.     for (int x = 0;x < 10; x++)  
  18.     {  
  19.         func();  
  20.     }  
  21. }  

    所以在C++文件中編譯C文件需要使用extern "C"關鍵字,聲明語法如下所示

    extern "C"

    {

        採用C語言實現的內容

    }

 

    方法二、

    在devVar.h文件中實現C代碼(即devVar.h作爲C語言頭文件),在.cpp文件中包含C語言頭文件。

    devVar.h頭文件內容爲:

   

[cpp] view plain copy
  1. #include <stdio.h>  
  2.   
  3. int i = 1;  
  4.   
  5. void func()  
  6. {  
  7.     printf("%d",i++);  
  8. }  

    extern.cpp文件內容如下所示

   

[cpp] view plain copy
  1. #include "stdafx.h"  
  2. #include <stdio.h>  
  3. #include <iostream>  
  4. using namespace std;  
  5. //#include "devVar.h"  
  6. //extern int i;  
  7. //extern void func();  
  8.   
  9. extern "C"  
  10. {  
  11.     //extern int i;  
  12.     //extern void func();  
  13.     #include "devVar.h"   
  14. }  
  15. int main(void)  
  16. {  
  17.     for (int x = 0;x < 10; x++)  
  18.     {  
  19.         func();  
  20.     }  
  21. }  

    其中,包含C語言頭文件的方式爲:

[cpp] view plain copy
  1. extern "C"  
  2. {  
  3.     //extern int i;  
  4.     //extern void func();  
  5.     #include "devVar.h"   
  6. }  

 

    寫到這裏,樓主又產生了一個疑問,上面的例子講的是C++調用C實現的代碼,那如果是C調用C++編寫的代碼呢?

    樓主作了如下改動:

    devVar.cpp代碼爲:   

[cpp] view plain copy
  1. #include <stdio.h>  
  2.   
  3. int i = 1;  
  4.   
  5. void func()  
  6. {  
  7.     printf("%d",i++);  
  8. }  

    extern.c文件代碼爲

[cpp] view plain copy
  1. #include <stdio.h>  
  2.   
  3. extern int i;  
  4. extern void func();  
  5.   
  6. int main(void)  
  7. {  
  8.     int x = 0;  
  9.     for (;x < 10; x++)  
  10.     {  
  11.         func();  
  12.     }  
  13. }  

    單獨編譯每個文件都通過,鏈接聲稱可執行文件的時候報錯:

    1>extern.obj : error LNK2019: unresolved external symbol _func referenced in function _main,說明.c文件中extern void func(),按照C編譯的規則,得到函數_func,而devVar.cpp文件採用C++編譯方式,得到的函數爲XX·!_func(具體樓主也不知道哈),這樣鏈接的時候函數自然找不到,那怎麼解決呢?

    需要在devVar.cpp中,明確調用extern "C"關鍵字,聲明cpp文件中有關代碼,需要按照C的方式來生成,修改devVar.cpp文件如下所示:

   

[cpp] view plain copy
  1.     #include <stdio.h>  
  2.   
  3.     int i = 1;  
  4.   
  5.   
  6. extern "C" void func()  
  7.     {  
  8.         printf("%d",i++);  
  9.     }  

     此時,除了需要使用extern "C"聲明編譯的時候採用C方式編譯外,.cpp文件中的代碼可以按照C++方式編寫,例如

     devVar.cpp按照下面方式寫,也是正確的。

    

[cpp] view plain copy
  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. using namespace std;  
  4.   
  5. int i = 1;  
  6.   
  7. extern "C" void func()  
  8.     {  
  9.         cout << "i = " << i++ << endl;  
  10.     }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章