///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
編譯鏈接
聲明外部變量
現(xiàn)代編譯器一般采用按文件編譯的方式,因此在編譯時,各個文件中定義的全局變量是互相不透明的。也就是說,在編譯時,全局變量的可見域限制在文件內(nèi)部。
下面舉一個簡單的例子:
創(chuàng)建一個工程,里面含有A.cpp和B.cpp兩個簡單的C++源文件:
//A.cpp
int i;
int main()
{
}
//B.cpp
int i;
這兩個文件極為簡單,在A.cpp中我們定義了一個全局變量i,在B中我們也定義了一個全局變量i。
我們對A和B分別編譯,都可以正常通過編譯,但是進行鏈接的時候,卻出現(xiàn)了錯誤,錯誤提示如下:
Linking...
B.obj:error?LNK2005:"inti"(?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時覺察不到B中也定義了i,同樣,編譯B時覺察不到A中也定義了i。
但是到了鏈接階段,要將各個文件的內(nèi)容“合為一體”,因此,如果某些文件中定義的全局變量名相同的話,在這個時候就會出現(xiàn)錯誤,也就是上面提示的重復定義的錯誤。
因此,各個文件中定義的全局變量名不可相同。
在鏈接階段,各個文件的內(nèi)容(實際是編譯產(chǎn)生的obj文件)是被合并到一起的,因而,定義于某文件內(nèi)的全局變量,在鏈接完成后,它的可見范圍被擴大到了整個程序。
這樣一來,按道理說,一個文件中定義的全局變量,可以在整個程序的任何地方被使用,舉例說,如果A文件中定義了某全局變量,那么B文件中應可以使用該變量。修改我們的程序,加以驗證:
//A.cpp
int main()
{
i?=?100;//試圖使用B中定義的全局變量
}
//B.cpp
int i;
編譯結(jié)果如下:
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)
編譯錯誤。
其實出現(xiàn)這個錯誤是意料之中的,因為文件中定義的全局變量的可見性擴展到整個程序是在鏈接完成之后,而在編譯階段,他們的可見性仍局限于各自的文件。
編譯器的目光不夠長遠,編譯器沒有能夠意識到,某個變量符號雖然不是本文件定義的,但是它可能是在其它的文件中定義的。
雖然編譯器不夠有遠見,但是我們可以給它提示,幫助它來解決上面出現(xiàn)的問題。這就是extern的作用了。
extern的原理很簡單,就是告訴編譯器:“你現(xiàn)在編譯的文件中,有一個標識符雖然沒有在本文件中定義,但是它是在別的文件中定義的全局變量,你要放行!”
我們?yōu)樯厦娴腻e誤程序加上extern關鍵字:
//A.cpp
extern int i;
intmain()
{
i=100;//試圖使用B中定義的全局變量
}
//B.cpp
inti;
順利通過編譯,鏈接。