聲明外部變量
現(xiàn)代編譯器一般采用按文件編譯的方式,因此在編譯時,各個文件中定義的全局變量是互相透明的,也就是說,在編譯時,全局變量的可見域限制在文件內(nèi)部。下面舉一個簡單的例子。創(chuàng)建一個工程,里面含有A.cpp和B.cpp兩個簡單的C++源文件:
//A.cpp inti; voidmain() { }
//B.cpp int i;
這兩個文件極為簡單,在A.cpp中定義了一個全局變量i,在B中也定義了一個全局變量i。對A和B分別編譯,都可以正常通過編譯,但是進(jìn)行鏈接的時候,卻出現(xiàn)了錯誤,錯誤提示如下:
Linking... B.obj:errorLNK2005:"inti"(?i@@3HA)alreadydefinedinA.obj Debug/A.exe:fatalerrorLNK1169:oneormoremultiplydefinedsymbolsfound Errorexecutinglink.exe. A.exe - 2 error(s), 0 warning(s)
這就是說,在編譯階段,各個文件中定義的全局變量相互是透明的,編譯A時覺察不到B中也定義了i,同樣,編譯B時覺察不到A中也定義了i。但是在鏈接階段,要將各個文件的內(nèi)容“合為一體”,因此,如果某些文件中定義的全局變量名相同的話,在鏈接階段就會報重復(fù)定義(oneormoremultiplydefinedsymbols)的錯誤。
因此,各個文件中定義的全局變量名不可相同。
在鏈接階段,編譯產(chǎn)生的obj文件合并了A、B兩文件的內(nèi)容,這也是出現(xiàn)int i重復(fù)定義錯誤的原因。
舉個例子
一個文件中定義的全局變量,可以在整個程序的任何地方被使用,舉例說,如果A文件中定義了某全局變量,那么B文件中也可以使用該變量。修改我們的程序,加以驗證:
//A.cpp voidmain() { i=100; //試圖使用B中定義的全局變量 }
//B.cpp int i;
出現(xiàn)如下意料之中的編譯錯誤,未定義int i錯誤(undeclaredidentifierError),因為在鏈接之前A、B文件中的變量是彼此不可見的。
Compiling... A.cpp C:/Documents and Settings/wangjian/桌面/try extern/A.cpp(5) : error C2065: 'i' : undeclared identifier Errorexecutingcl.exe. A.obj-1error(s),0warning(s)
編譯器沒有能夠意識到,某個變量符號雖然不是本文件定義的,但是它可能是在其它的文件中定義的,為了避免錯誤的發(fā)生extern派上用場了。為上面的錯誤程序加上extern關(guān)鍵字后,順利通過編譯,鏈接,代碼如下:
//A.cpp externinti; voidmain() { i=100;//試圖使用B中定義的全局變量 }
//B.cpp int i;
在C++文件中調(diào)用C方式編譯的函數(shù)
相對于C,C++中新增了諸如重載等新特性,它們的編譯有一些重要區(qū)別。將下面的小程序分別按C和C++方式編譯,來探討兩種編譯方式的區(qū)別。
inti; intfunc(intt) { return0; } voidmain() { }
以C方式編譯的結(jié)果如下:
COMM_i:DWORD PUBLIC_func PUBLIC _main
以C++方式編譯的結(jié)果如下:
PUBLIC?i@@3HA;i PUBLIC?func@@YAHH@Z;func PUBLIC _main
可見,C方式編譯下,變量名和函數(shù)名之前被統(tǒng)一加上了一個下劃線,而C++編譯后的結(jié)果卻復(fù)雜的多,i變成了?i@@ 3HA ,func變成了?func@@YAHH@Z。C++中的這種看似復(fù)雜的命名規(guī)則是為C++中的函數(shù)重載,參數(shù)檢查等特性服務(wù)的。
不同編譯方式下的函數(shù)調(diào)用
如果在工程中,不僅有CPP文件,還有以C方式編譯的C文件,函數(shù)調(diào)用就會有一些微妙之處。有如下CPP文件A.CPP和C文件B.C兩個文件。
//A.CPP voidfunc(); voidmain() { func(); }
//B.C void func() { }
對A.CPP和B.C分別編譯,都沒有問題,但是鏈接時出現(xiàn)錯誤,原因就是C和CPP不同的編譯方式產(chǎn)生的沖突。比如在上文中提到,C方式編譯下,變量名和函數(shù)名之前被統(tǒng)一加上了一個下劃線,而C++編譯后的結(jié)果卻復(fù)雜的多,i變成了?i@@ 3HA。
Linking... A.obj:errorLNK2001:unresolvedexternalsymbol"void__cdeclfunc(void)"(?func@@YAXXZ) Debug/A.exe:fatalerrorLNK1120:1unresolvedexternals Errorexecutinglink.exe. A.exe - 2 error(s), 0 warning(s)
此時,可以通過extern關(guān)鍵字,來幫助編譯器解決上面提到的問題。對于本例,只需將A.CPP改成如下代碼即可:
//A.CPP extern "C" { void func(); //引入C語言方式編譯的函數(shù)或變量 } void main() { func(); }
審核編輯:湯梓紅
-
函數(shù)
+關(guān)注
關(guān)注
3文章
4331瀏覽量
62618 -
C++
+關(guān)注
關(guān)注
22文章
2108瀏覽量
73651 -
編譯器
+關(guān)注
關(guān)注
1文章
1634瀏覽量
49132 -
extern
+關(guān)注
關(guān)注
0文章
7瀏覽量
2952
原文標(biāo)題:C/C++語言中extern的用法
文章出處:【微信號:單片機(jī)與嵌入式,微信公眾號:單片機(jī)與嵌入式】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論