聲明外部變量
現(xiàn)代編譯器一般采用按文件編譯的方式,因此在編譯時(shí),各個(gè)文件中定義的全局變量是互相透明的,也就是說(shuō),在編譯時(shí),全局變量的可見(jiàn)域限制在文件內(nèi)部。下面舉一個(gè)簡(jiǎn)單的例子。創(chuàng)建一個(gè)工程,里面含有A.cpp和B.cpp兩個(gè)簡(jiǎn)單的C++源文件:
//A.cpp inti; voidmain() { }
//B.cpp int i;
這兩個(gè)文件極為簡(jiǎn)單,在A.cpp中定義了一個(gè)全局變量i,在B中也定義了一個(gè)全局變量i。對(duì)A和B分別編譯,都可以正常通過(guò)編譯,但是進(jìn)行鏈接的時(shí)候,卻出現(xiàn)了錯(cuò)誤,錯(cuò)誤提示如下:
Linking... B.obj:errorLNK2005:"inti"(?i@@3HA)alreadydefinedinA.obj Debug/A.exe:fatalerrorLNK1169:oneormoremultiplydefinedsymbolsfound Errorexecutinglink.exe. A.exe - 2 error(s), 0 warning(s)
這就是說(shuō),在編譯階段,各個(gè)文件中定義的全局變量相互是透明的,編譯A時(shí)覺(jué)察不到B中也定義了i,同樣,編譯B時(shí)覺(jué)察不到A中也定義了i。但是在鏈接階段,要將各個(gè)文件的內(nèi)容“合為一體”,因此,如果某些文件中定義的全局變量名相同的話,在鏈接階段就會(huì)報(bào)重復(fù)定義(oneormoremultiplydefinedsymbols)的錯(cuò)誤。
因此,各個(gè)文件中定義的全局變量名不可相同。
在鏈接階段,編譯產(chǎn)生的obj文件合并了A、B兩文件的內(nèi)容,這也是出現(xiàn)int i重復(fù)定義錯(cuò)誤的原因。
舉個(gè)例子
一個(gè)文件中定義的全局變量,可以在整個(gè)程序的任何地方被使用,舉例說(shuō),如果A文件中定義了某全局變量,那么B文件中也可以使用該變量。修改我們的程序,加以驗(yàn)證:
//A.cpp voidmain() { i=100; //試圖使用B中定義的全局變量 }
//B.cpp int i;
出現(xiàn)如下意料之中的編譯錯(cuò)誤,未定義int i錯(cuò)誤(undeclaredidentifierError),因?yàn)樵阪溄又癆、B文件中的變量是彼此不可見(jiàn)的。
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)
編譯器沒(méi)有能夠意識(shí)到,某個(gè)變量符號(hào)雖然不是本文件定義的,但是它可能是在其它的文件中定義的,為了避免錯(cuò)誤的發(fā)生extern派上用場(chǎng)了。為上面的錯(cuò)誤程序加上extern關(guān)鍵字后,順利通過(guò)編譯,鏈接,代碼如下:
//A.cpp externinti; voidmain() { i=100;//試圖使用B中定義的全局變量 }
//B.cpp int i;
在C++文件中調(diào)用C方式編譯的函數(shù)
相對(duì)于C,C++中新增了諸如重載等新特性,它們的編譯有一些重要區(qū)別。將下面的小程序分別按C和C++方式編譯,來(lái)探討兩種編譯方式的區(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
可見(jiàn),C方式編譯下,變量名和函數(shù)名之前被統(tǒng)一加上了一個(gè)下劃線,而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)用就會(huì)有一些微妙之處。有如下CPP文件A.CPP和C文件B.C兩個(gè)文件。
//A.CPP voidfunc(); voidmain() { func(); }
//B.C void func() { }
對(duì)A.CPP和B.C分別編譯,都沒(méi)有問(wèn)題,但是鏈接時(shí)出現(xiàn)錯(cuò)誤,原因就是C和CPP不同的編譯方式產(chǎn)生的沖突。比如在上文中提到,C方式編譯下,變量名和函數(shù)名之前被統(tǒng)一加上了一個(gè)下劃線,而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)
此時(shí),可以通過(guò)extern關(guān)鍵字,來(lái)幫助編譯器解決上面提到的問(wèn)題。對(duì)于本例,只需將A.CPP改成如下代碼即可:
//A.CPP extern "C" { void func(); //引入C語(yǔ)言方式編譯的函數(shù)或變量 } void main() { func(); }
審核編輯:湯梓紅
-
函數(shù)
+關(guān)注
關(guān)注
3文章
4381瀏覽量
64948 -
C++
+關(guān)注
關(guān)注
22文章
2119瀏覽量
75363 -
編譯器
+關(guān)注
關(guān)注
1文章
1662瀏覽量
50249 -
extern
+關(guān)注
關(guān)注
0文章
7瀏覽量
3069
原文標(biāo)題:C/C++語(yǔ)言中extern的用法
文章出處:【微信號(hào):?jiǎn)纹瑱C(jī)與嵌入式,微信公眾號(hào):?jiǎn)纹瑱C(jī)與嵌入式】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
C語(yǔ)言中枚舉的基本概念和常見(jiàn)用法
C語(yǔ)言中的數(shù)據(jù)類型有哪幾種?const有哪些用法?
c語(yǔ)言中typedef的用法
解析C語(yǔ)言與ARM匯編與的相互調(diào)用以及與 C++ 相互調(diào)用
C++語(yǔ)言的基本構(gòu)成詳細(xì)資料說(shuō)明

C語(yǔ)言中的#和##的用法

C語(yǔ)言和C++的特點(diǎn)與用法詳細(xì)說(shuō)明
你真的知道C語(yǔ)言里extern C有什么作用嗎

C語(yǔ)言中的extern

C語(yǔ)言中的typedef的用法

C語(yǔ)言中的extern
詳解C語(yǔ)言中特殊用法
淺析C語(yǔ)言中的regiseter關(guān)鍵字

評(píng)論