聲明外部變量
現代編譯器一般采用按文件編譯的方式,因此在編譯時,各個文件中定義的全局變量是互相透明的,也就是說,在編譯時,全局變量的可見域限制在文件內部。下面舉一個簡單的例子。創(chuàng)建一個工程,里面含有A.cpp和B.cpp兩個簡單的C++源文件:
//A.cpp inti; voidmain() { }
//B.cpp int i;
這兩個文件極為簡單,在A.cpp中定義了一個全局變量i,在B中也定義了一個全局變量i。對A和B分別編譯,都可以正常通過編譯,但是進行鏈接的時候,卻出現了錯誤,錯誤提示如下:
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。但是在鏈接階段,要將各個文件的內容“合為一體”,因此,如果某些文件中定義的全局變量名相同的話,在鏈接階段就會報重復定義(oneormoremultiplydefinedsymbols)的錯誤。
因此,各個文件中定義的全局變量名不可相同。
在鏈接階段,編譯產生的obj文件合并了A、B兩文件的內容,這也是出現int i重復定義錯誤的原因。
舉個例子
一個文件中定義的全局變量,可以在整個程序的任何地方被使用,舉例說,如果A文件中定義了某全局變量,那么B文件中也可以使用該變量。修改我們的程序,加以驗證:
//A.cpp voidmain() { i=100; //試圖使用B中定義的全局變量 }
//B.cpp int i;
出現如下意料之中的編譯錯誤,未定義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關鍵字后,順利通過編譯,鏈接,代碼如下:
//A.cpp externinti; voidmain() { i=100;//試圖使用B中定義的全局變量 }
//B.cpp int i;
在C++文件中調用C方式編譯的函數
相對于C,C++中新增了諸如重載等新特性,它們的編譯有一些重要區(qū)別。將下面的小程序分別按C和C++方式編譯,來探討兩種編譯方式的區(qū)別。
inti; intfunc(intt) { return0; } voidmain() { }
以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++中的這種看似復雜的命名規(guī)則是為C++中的函數重載,參數檢查等特性服務的。
不同編譯方式下的函數調用
如果在工程中,不僅有CPP文件,還有以C方式編譯的C文件,函數調用就會有一些微妙之處。有如下CPP文件A.CPP和C文件B.C兩個文件。
//A.CPP voidfunc(); voidmain() { func(); }
//B.C void func() { }
對A.CPP和B.C分別編譯,都沒有問題,但是鏈接時出現錯誤,原因就是C和CPP不同的編譯方式產生的沖突。比如在上文中提到,C方式編譯下,變量名和函數名之前被統一加上了一個下劃線,而C++編譯后的結果卻復雜的多,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關鍵字,來幫助編譯器解決上面提到的問題。對于本例,只需將A.CPP改成如下代碼即可:
//A.CPP extern "C" { void func(); //引入C語言方式編譯的函數或變量 } void main() { func(); }
審核編輯:湯梓紅
-
函數
+關注
關注
3文章
4365瀏覽量
63940 -
C++
+關注
關注
22文章
2116瀏覽量
74639 -
編譯器
+關注
關注
1文章
1653瀏覽量
49770 -
extern
+關注
關注
0文章
7瀏覽量
3023
原文標題:C/C++語言中extern的用法
文章出處:【微信號:單片機與嵌入式,微信公眾號:單片機與嵌入式】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
C語言中枚舉的基本概念和常見用法
C語言中的數據類型有哪幾種?const有哪些用法?
c語言中typedef的用法
解析C語言與ARM匯編與的相互調用以及與 C++ 相互調用
C++語言的基本構成詳細資料說明

C語言中的#和##的用法

C語言中的extern

C語言中的typedef的用法

評論