extern作用詳解

2021-06-22 08:56:24 字數 3066 閱讀 7488

extern 作用1:宣告外部變數

現代編譯器一般採用按檔案編譯的方式,因此在編譯時,各個檔案中定義的全域性變數是

互相透明的,也就是說,在編譯時,全域性變數的可見域限制在檔案內部。

例1:建立乙個工程,裡面含有a.cpp和b.cpp兩個簡單的c++原始檔:

int iri;

int main()

int iri;

gcc a.cpp -c

gcc b.cpp -c

編譯出a.o, b.o都沒有問題。

但當gcc a.o b.o -o test時,

main.o:(.bss+0x0): multiple definition of `iri'

b.o:(.bss+0x0): first defined here

報錯:重定義。

(但有個非常意外的發現:當同樣的**,使用a.c b.c.並使用gcc編譯時,竟然不會報重定義的錯誤,非常不明白是怎麼回事。)

這就是說,在編譯階段,各個檔案中定義的全域性變數相互是透明的,編譯a時覺察不到b中也定義了i,同樣,編譯b時覺察不到a中也定義了i。

但是到了鏈結階段,要將各個檔案的內容「合為一體」,因此,如果某些檔案中定義的全域性變數名相同的話,在這個時候就會出現錯誤,也就是上面提示的重複定義的錯誤。因此,各個檔案中定義的全域性變數名不可相同。

但如果用下列方式:在b.cpp中定義iri;在a.cpp中直接使用。則編譯a.cpp時就無法通過。

int main()

int iri;

gcc a.cpp -c

was not declared in this scope.

因為編譯器按照檔案方式編譯,所以編譯a.cpp時,並不知道b.cpp中定義了iri。

也就是說:檔案中定義的全域性變數的可見性擴充套件到整個程式是在鏈結完成之後,而在編譯階段,他們的可見性仍侷限於各自的檔案。

解決方案如下:

編譯器的目光不夠長遠,編譯器沒有能夠意識到,某個變數符號雖然不是本檔案定義的,但是它可能是在其它的檔案中定義的。

雖然編譯器不夠遠見,但是我們可以給它提示,幫助它來解決上面出現的問題。這就是extern的作用了。

extern的原理很簡單,就是告訴編譯器:「你現在編譯的檔案中,有乙個識別符號雖然沒有在本檔案中定義,但是它是在別的檔案中定義的全域性變數,你要放行!」

extern int iri;

int main()

int iri;

這樣編譯就能夠通過。

extern int iri; //並未分配空間,只是通知編譯器,在其它檔案定義過iri。

extern 作用2:在c++檔案中呼叫c方式編譯的函式

c方式編譯和c++方式編譯

相對於c,c++中新增了諸如過載等新特性。所以全域性變數和函式名編譯後的命名方式有很大區別。

int a;

int functiona();

對於c方式編譯:

int a;=> _a

int functiona(); => _functiona

對於c++方式編譯:

int a; =>xx@***@a

int functiona(); =>

xx@xx@functiona

可以看出,因為要支援過載,所以c++方式編譯下,生成的全域性變數名和函式名複雜很多。與c方式編譯的加乙個下劃線不同。

於是就有下面幾種情況:

例2:c++呼叫c++定義的全域性變數

extern int iri;

int main()

int iri;

gcc a.cpp -c

gcc b.cpp -c

gcc a.o b.o -o test

那麼在編譯鏈結時都沒問題。

例3:c++呼叫c定義的全域性變數

extern int iri;

int main()

int iri;

編譯時沒有問題,

gcc a.cpp -c

gcc b.c -c

但鏈結時,gcc b.o a.o -o test

則會報iri沒有定義。為什麼呢?

因為gcc看到a.cpp,就使用c++方式編譯,看到b.c,就使用c方式編譯。

所以在a.cpp中的iri=>***@***_iri;

而b.c中iri=〉_iri;

所以在鏈結時,a.cpp想找到

***@***_iri

,當然找不到。所以就需要告訴編譯器,iri是使用c方式編譯的。

extern "c"

int main()

int iri;

這樣,當編譯a.cpp時,編譯器就知道iri為c方式編譯的。就會使用 _iri。這樣b.c提供的_iri就可以被a.cpp找到了。

例4:c++呼叫c定義的function

extern int functiona();

int main()

int functiona()

gcc a.cpp -c

gcc b.c -c

都沒有問題。但同樣的,gcc a.o b.o -o test

則報錯,找不到functiona();

這是因為gcc將a.cpp認為是c++方式編譯,b.c是c方式編譯。

所以functiona在b.c中為:_functiona. 在a.cpp中為:

xx@***_functiona

所以在鏈結時a.cpp找不到

xx@xx_function

.於是需要通知編譯器,functiona()是c方式編譯命名的。

extern "c"

int main()

int functiona()

於是,編譯鏈結都可以通過。

總結:extern "c"

//不止是宣告,並且還指出:這個function請用c方式編譯。所以不需要再次extern.

extern"c"

//這樣做沒什麼太大意義。 0

給主人留下些什麼吧!~~

extern作用詳解

extern 作用1 宣告外部變數 現代編譯器一般採用按檔案編譯的方式,因此在編譯時,各個檔案中定義的全域性變數是 互相透明的,也就是說,在編譯時,全域性變數的可見域限制在檔案內部。例1 建立乙個工程,裡面含有a.cpp和b.cpp兩個簡單的c 原始檔 int iri int main int ir...

extern 作用詳解

extern 作用詳解 extern 作用1 宣告外部變數 現代編譯器一般採用按檔案編譯的方式,因此在編譯時,各個檔案中定義的全域性變數是 互相透明的,也就是說,在編譯時,全域性變數的可見域限制在檔案內部。例1 建立乙個工程,裡面含有a.cpp和b.cpp兩個簡單的c 原始檔 int iri int...

extern用法詳解

1 基本解釋 extern可以置於變數或者函式 前,以標示變數或者函式 的定義在別的檔案中,提示編譯器遇到此變數和函式 時在其他模組中尋找其定義。另外,extern也可用來進行鏈結指定。2 問題 extern 變數 在乙個原始檔裡定義了乙個陣列 char a 6 在另外乙個檔案裡用下列語句進行了宣告...