chapter 1 . extern關鍵字的作用
extern是一個關鍵字,它告訴編譯器存在着一個變量或者一個函數,如果在當前編譯語句的前面中沒有找到相應的變量或者函數,也會在當前文件的後面或者其它文件中定義,來看下面的例子。
- // extern.cpp : Defines the entry point for the console application.
- //
- #include "stdafx.h"
- #include <iostream>
- using namespace std;
- extern int i;
- extern void func();
- int _tmain(int argc, _TCHAR* argv[])//typedef wchar_t _TCHAR;#define _tmain wmain
- {
- i = 0;
- func();
- return 0;
- }
- int i;
- void func()
- {
- i++;
- cout << "i = " << i << endl;
- }
上面代碼中變量i和函數func在文件末尾定義,所以變量需要使用extern關鍵字告訴編譯器,變量在別的地方定義。extern int i我原來以爲extern i就可以,結果編譯器報錯,仔細想下確實應該,否則編譯器不知道i是什麼類型的數據,又怎麼能判斷i = 0是否是一個正確的賦值語句呢?
那麼定義在其他文件中的函數和變量,如何通過extern關鍵字調用呢?
首先,定義在其它文件中的函數和變量,可以使用兩種方法調用:
一、使用頭文件調用,這時候,函數和變量必須在頭文件中定義和聲明。
二、使用extern關鍵字調用,這時候函數和變量在.cpp或者.c文件中定義和聲明。
看下面兩個例子:
devVar.cpp函數中定義:
- #include "stdafx.h"
- int i;
extern.cpp中
- // extern.cpp : Defines the entry point for the console application.
- //
- #include "stdafx.h"
- #include <iostream>
- using namespace std;
- extern int i;
- extern void func();
- int _tmain(int argc, _TCHAR* argv[])//typedef wchar_t _TCHAR;#define _tmain wmain
- {
- i = 0;
- func();
- return 0;
- }
- void func()
- {
- i++;
- cout << "i = " << i << endl;
- }
編譯工程,程序輸出:i = 1,這裏使用extern關鍵字聲明在其它cpp文件中定義的變量和函數。
#include <filensme> --- 將filename文件中的內容插入到新的文件中。
deVar.h文件中代碼爲
- #include <stdio.h>
- int i = 1;
- void func()
- {
- printf("%d",i++);
- }
函數func修改全局變量i的值並輸出。
extern.cpp文件內容爲:
- #include "stdafx.h"
- #include <stdio.h>
- #include <iostream>
- using namespace std;
- #include "devVar.h"
- //extern int i;
- //extern void func();
- int main(void)
- {
- for (int x = 0;x < 10; x++)
- {
- func();
- }
- }
程序輸出1,2,3,4,5,6,7,8,9,10,這裏#include <filname.h> 包含定義在其它頭文件中的函數和變量,在來看一個例子。
- // extern.cpp : Defines the entry point for the console application.
- //
- #include "stdafx.h"
- #include <iostream>
- using namespace std;
- extern int i;
- extern int func(int);//這裏extern必需的,函數定義在其它cpp文件中
- int _tmain(int argc, _TCHAR* argv[])//typedef wchar_t _TCHAR;#define _tmain wmain
- {
- i = 100;
- func(i);
- return 0;
- }
devVar.cpp文件中內容爲:
- #include "stdafx.h"
- #include <iostream>
- using namespace std;
- int i;
- int func(int a)
- {
- i = a;
- cout << "i = " << i << endl;
- return 0;
- }
這樣,同樣是輸出了i= 100。
能夠使用extern引用其它cpp文件中定義的函數說明了一個問題:
如果一個工程現編譯cpp文件,在把多個目標文件鏈接成爲可執行文件,而兩個或多個文件中,定義了相同的全局變量,那麼,程序編譯的時候不會報錯,因爲編譯器單獨編譯每個文件,在鏈接可執行文件的時候,由於多個目標文件中含有相同的全局變量,而生成可執行文件的時候,任何文件中定義的全局變量對其它目標文件都是可見的,此時由於變量定義衝突而發生錯誤。看下面的代碼:
- // extern.cpp : Defines the entry point for the console application.
- //
- #include "stdafx.h"
- #include <iostream>
- using namespace std;
- int i;
- extern int func(int);//這裏extern是必須的函數定義在別的cpp文件中
- int _tmain(int argc, _TCHAR* argv[])//typedef wchar_t _TCHAR;#define _tmain wmain
- {
- i = 100;
- func(i);
- return 0;
- }
devVar.cpp文件中,內容爲:
- #include "stdafx.h"
- #include <iostream>
- using namespace std;
- int i;
- int func(int a)
- {
- i = a;
- cout << "i = " << i << endl;
- return 0;
- }
單獨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文件的代碼如下所示:
- #include <stdio.h>
- int i = 1;
- void func()
- {
- printf("%d",i++);
- }
extern.cpp文件中代碼如下所示:
- #include "stdafx.h"
- #include <stdio.h>
- #include <iostream>
- using namespace std;
- //#include "devVar.h"
- //extern int i;
- //extern void func();
- extern "C"
- {
- extern int i;
- extern void func();
- //#include "devVar.h"
- }
- int main(void)
- {
- for (int x = 0;x < 10; x++)
- {
- func();
- }
- }
所以在C++文件中編譯C文件需要使用extern "C"關鍵字,聲明語法如下所示
extern "C"
{
採用C語言實現的內容
}
方法二、
在devVar.h文件中實現C代碼(即devVar.h作爲C語言頭文件),在.cpp文件中包含C語言頭文件。
devVar.h頭文件內容爲:
- #include <stdio.h>
- int i = 1;
- void func()
- {
- printf("%d",i++);
- }
extern.cpp文件內容如下所示
- #include "stdafx.h"
- #include <stdio.h>
- #include <iostream>
- using namespace std;
- //#include "devVar.h"
- //extern int i;
- //extern void func();
- extern "C"
- {
- //extern int i;
- //extern void func();
- #include "devVar.h"
- }
- int main(void)
- {
- for (int x = 0;x < 10; x++)
- {
- func();
- }
- }
其中,包含C語言頭文件的方式爲:
- extern "C"
- {
- //extern int i;
- //extern void func();
- #include "devVar.h"
- }
寫到這裏,樓主又產生了一個疑問,上面的例子講的是C++調用C實現的代碼,那如果是C調用C++編寫的代碼呢?
樓主作了如下改動:
devVar.cpp代碼爲:
- #include <stdio.h>
- int i = 1;
- void func()
- {
- printf("%d",i++);
- }
extern.c文件代碼爲
- #include <stdio.h>
- extern int i;
- extern void func();
- int main(void)
- {
- int x = 0;
- for (;x < 10; x++)
- {
- func();
- }
- }
單獨編譯每個文件都通過,鏈接聲稱可執行文件的時候報錯:
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文件如下所示:
- #include <stdio.h>
- int i = 1;
- extern "C" void func()
- {
- printf("%d",i++);
- }
此時,除了需要使用extern "C"聲明編譯的時候採用C方式編譯外,.cpp文件中的代碼可以按照C++方式編寫,例如
devVar.cpp按照下面方式寫,也是正確的。
- #include "stdafx.h"
- #include <iostream>
- using namespace std;
- int i = 1;
- extern "C" void func()
- {
- cout << "i = " << i++ << endl;
- }