1、 聲明外部變量
//A.cpp
int i;
void main()
{
}
//B.cpp
int i;
這兩個文件極爲簡單,在A.cpp中我們定義了一個全局變量i,在B中我們也定義了一個全局變量i。
我們對A和B分別編譯,都可以正常通過編譯,但是進行鏈接的時候,卻出現了錯誤,錯誤提示如下:
Linking...
B.obj : error LNK2005: "int i" (?i@@3HA) already defined in A.obj
Debug/A.exe : fatal error LNK1169: one or more multiply defined symbols found
Error executing link.exe.
A.exe - 2 error(s), 0 warning(s)
//A.cpp
void main()
{
i = 100; //試圖使用B中定義的全局變量
}
//B.cpp
int i;
編譯結果如下:
Compiling...
A.cpp
C:/Documents and Settings/wangjian/桌面/try extern/A.cpp(5) : error C2065: 'i' : undeclared identifier
Error executing cl.exe.
A.obj - 1 error(s), 0 warning(s)
編譯錯誤。其實出現這個錯誤是意料之中的,因爲:文件中定義的全局變量的可見性擴展到整個程序是在鏈接完成之後,而在編譯階段,他們的可見性仍侷限於各自的文件。
//A.cpp
extern int i;
void main()
{
i = 100; //試圖使用B中定義的全局變量
}
//B.cpp
int i;
順利通過編譯,鏈接。
2、 在C++文件中調用C方式編譯的函數
int i;
int func(int t)
{
return 0;
}
void main()
{
}
以C方式編譯的結果:
COMM _i : DWORD
PUBLIC _func
PUBLIC _main
以C++方式編譯的結果:
PUBLIC ?i@@3HA ; i
PUBLIC ?func@@YAHH@Z ; func
PUBLIC _main
可見,C方式編譯下,變量名和函數名之前被統一加上了一個下劃線,而C++編譯後的結果卻複雜的多,i變成了?i@@3HA,func變成了?func@@YAHH@Z。C++中的這種看似複雜的命名規則是爲C++中的函數重載,參數檢查等特性服務的。
多文件程序中的函數調用
一般情況下,工程中的文件都是CPP文件(以及頭文件)。如下面的程序僅包含兩個文件:A.CPP和B.CPP:
//A.CPP
void func();
void main()
{
func();
}
//B.CPP
void func()
{
}
程序的結構是這樣的:在文件B.CPP中定義了一個函數void func(),main函數位於文件A.CPP,在main函數中調用了B中定義的函數func()。要在A中調用B中定義的函數,必須要加上該函數的聲明。如本例中的void func();就是對函數func()的聲明。
需要注意的是,一般的程序都是通過包含頭文件來完成函數的聲明。拿本例來說,一般是創建一個頭文件B.H,在頭文件中加入聲明語句void func(); 並且在A.CPP中加入包含語句:#include “B.H”。
在C++程序中,頭文件的功能從函數聲明被擴展爲類的定義。
//A.CPP
void func();
void main()
{
func();
}
//B.C
void func()
{
}
Linking...
A.obj : error LNK2001: unresolved external symbol "void __cdecl func(void)" (?func@@YAXXZ)
Debug/A.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
A.exe - 2 error(s), 0 warning(s)
如果B文件也是按照C++方式編譯的,那麼B中的func函數名也會被編譯器改成?func1@@YAXXZ,這樣的話,就沒有任何問題。
對A.CPP和B.C分別編譯,都沒有問題,但是鏈接時出現錯誤。原因就在於不同的編譯方式產生的衝突。對於文件A,是按照C++的方式進行編譯的,其中的func()調用被編譯成了call ?func1@@YAXXZ//A.CPP
extern "C"
{
void func();
}
void main()
{
func();
}
3、 補充
同2一樣,仍然是C,C++混合編程的情形,考慮下面的程序:
/A.CPP
extern int i;
void main()
{ i = 100; }
//B.C
int i;
程序很簡單:在文件B.C中定義了一個全局變量i,在A.CPP中使用了這個全局變量。
這是因爲,在C方式編譯下,i被重命名爲_i,而在C++方式下,i會被重命名爲?i@@3HA。
因而,我們只用extern int i;來聲明還不夠,必須告訴編譯器,全局變量i是以C方式編譯的,
它會被重命名爲_i,而不是?i@@3HA。
我們修改A.CPP,如下: 程序正常通過編譯和鏈接。
//A.CPP
extern "C"
{
int i;
}
void main()
{
i = 100;
}
我們察看一下彙編代碼,發現語句i = 100;被編譯成了mov DWORD PTR _i, 100。
Linking...
A.obj : error LNK2001: unresolved external symbol "int i" (?i@@3HA)
Debug/A.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
A.exe - 2 error(s), 0 warning(s)