C 之關鍵字extern

2021-08-08 20:27:23 字數 2544 閱讀 7348

最近看了許多關於extern關鍵字的文章,有一些心得體會,本篇博文綜合了許多文章的內容,不正確的地方還希望大家能夠給予指正!

其中先指明乙個誤區:許多人認為標頭檔案只能包含宣告,這其實是不對的!

一、首先,讓我們來了解宣告和定義的基本概念。

1.1.宣告的概念

大概來講宣告主要是為了支援模組/編譯單元(.cpp)的編譯和鏈結,標頭檔案中的宣告可以讓其他模組知道所用物件的鏈結資訊而不需要知道實現細節。

而從細節方面來講:假若我宣告了變數int a,會在編譯器編譯階段填寫對映元素中的型別欄中填入int,名字欄中填入a,(所謂的對映元素包含變數或函式的型別欄、名字欄和位址列),並在後續**中找到使用該變數的地方並都填上相應的型別和名字。從這裡可以看出,由於位址列還是空著的,所以宣告並不分配記憶體空間,所以宣告可以進行多次。

1.2.定義的概念

定義用來生成對映元素的位址列,同時將後續**中用到該變數的地方都填入相同位址列,完成了記憶體分配的工作,使物件能夠找到自己的實體,因此定義只能進行一次。

小結:宣告用在編譯階段,用來檢查型別、名字及引數值;定義用在鏈結階段,如果只宣告而未定義,在程式編譯階段並不會報錯,但在鏈結階段會報link錯誤。

二、宣告可以分為變數的宣告、函式的宣告和類的宣告三種,下面將一一介紹:

2.1.變數的宣告

extern int i ;  //變數的宣告

extern int i = 1;  //變數的宣告,只有extern中不存在初始化才是宣告

int i;  //變數的定義

int i = 1;  //變數定義後並初始化

用來告訴編譯器該變數的型別。

2.2.函式的宣告

函式的定義和宣告很容易區分,這是因為函式定義後一定會接符合語句,而函式的宣告因為最後不會接,而是直接接了個;很容易區分,所以就預設不新增extern與新增extern的效果是一致的。

extern void a(long);  //以分號結尾,函式的宣告,extern等同於不寫

void a(long);  //以分號結尾,函式的宣告

void a(long)  //以復合語句結尾,函式的定義

函式宣告的作用如下:

1.使編譯器正確處理返回值

2.使編譯器可以檢查輸入引數的數目

3.使編譯器檢查輸入引數的型別,如果型別不正確,則對型別進行隱式轉換

2.3.類的宣告

類分為宣告、定義、實現三個部分

類的宣告又稱為類的前向宣告,告訴編譯器class的型別,但是並不知道其具體實現細節。

class a;  //類的前置宣告

此時使用sizeof(a)會報錯。

類的定義中則包含了對資料成員(變數)的定義和對函式成員的宣告,此時實際上已經給類中的資料成員分配了記憶體空間。使用sizeof(a)會顯示類中資料成員對齊後所占用的記憶體空間大小。

class a

//類的定義

因為在類的定義中並沒有完成函式的定義,所以在類的實現中完成成員函式的定義,類的實現在.cpp檔案中。

int a::geta()  //類的實現

三、那麼extern關鍵字如何使用?

3.1.宣告函式或全域性變數的作用域範圍

如在b.cpp中需要使用到a.cpp中的變數int g_a,則有兩種方法。

第一種:在a.h中宣告變數『extern int g_a;』然後在b.cpp中寫入『include"a.h"』;即可。

第二種:直接在b.cpp中寫入『extern int g_a;』這樣就不用再b.cpp中『include"a.h";』了。

也就是說用extern宣告的變數可以在本模組或其他模組中使用,即b模組(編譯單元)中要使用到a模組(編譯單元)中定義的全域性變數或函式時,只需要包含a的標頭檔案就可以了,這樣b雖然在編譯階段找不到該變數或函式的實體,但它不會報錯,它會在鏈結階段鏈結a生成的目標**找到相應的變數或函式。

3.2.extern與"c"連用

c++相對於c能夠實現乙個很重要的功能,即函式的過載,這是因為在c++對這幾個過載函式進行編譯時實際上是將返回值、函式名、引數型別、引數個數組合起來形成了乙個新的名字,所以過載函式實際並不同名,例如void a(),void* a(long), void a(long, short)將被分別翻譯為

「?abc@@yaxxz」、「?abc@@yapaxj@z」、「?abc@@yaxjf@z」,在這裡多說一句,過載函式實際上在編譯階段就已經被區分出來了,所以函式過載又被稱為編譯時多型。而c語言在編譯時則只是單純的再識別符號前加上_,所以上面的3個函式均會被編譯成_a,在編譯階段就會報錯說重定義。

那麼什麼時候按c語言風格編譯,什麼時候按c++語言風格編譯呢?

extern "c" void a();  //按c語言風格編譯

extern "c++" void a();  //按c++語言風格編譯

在.cpp檔案中預設extern "c++",在.c檔案中預設extern "c",不用寫出,如果想在.cpp中使用c語言風格編譯,在顯示寫出extern "c"。

好了,本篇就到這裡結束了,俺也寫累了

C語言關鍵字之extern

目錄 1.extern對變數的宣告 1.1在標頭檔案中宣告為全域性變數 1.2在main.c檔案中呼叫變數a之前將a宣告為全域性變數 1.3定義時直接宣告為全域性變數 2.extern對函式的宣告 2.1在標頭檔案中宣告為全域性函式 2.2在.c檔案中呼叫之前將函式宣告為全域性函式 2.3定義時直接...

C C 之關鍵字extern

typist akame qixisi excel bloonow extern是計算機語言c c 中乙個關鍵字,可用於變數或函式前 對於使用者,它宣告乙個外部符號,以表示該變數或函式是定義在別的檔案中的外部符號 對於建立者,它用在標頭檔案中的乙個宣告之前或乙個定義之前,顯式說明該符號可以被其他檔案...

C 的extern關鍵字

extern是乙個宣告,不是乙個定義,a模組想應用b模組的乙個函式或者變數,a模組包含b模組的標頭檔案,並且在變數或者標頭檔案前,加 extern,雖然編譯的時候,找不到模組的定義,但是在連線的時候,會在b模組生成的 中,找到函式或者變數。1 外部用的時候,不能乙個定義陣列,乙個定義指標這種 2 變...