extern C 與函式過載機制

2021-07-10 20:19:25 字數 1464 閱讀 6052

先來看一下下面這道題:

在c++程式中被c編譯器編譯後的函式,為什麼要加extern 「c」?

我們來寫乙個簡單的程式測試一下。

先寫乙個c++程式,簡單的求兩個數的和。

#includeusing namespace std;

extern int add(int ,int);

int main()

1>test.obj : error lnk2019: 無法解析的外部符號 "int __cdecl add(int,int)" (?add@@yahhh@z),該符號在函式 _main 中被引用。

(其中_cdecl是一種呼叫約定。)

這是為什麼呢?其實c與c++的命名方式是不同的,c語言中,函式的命名方式比較簡單,在函式名前加乙個_。而在c++中,函式的命名方式後面還會跟一些特殊符號和字母。

比如:這是在c語言中add函式的命名方式:

而在c++中,add函式是這樣命名的:

所以,在c++中,呼叫函式時編譯器是下面這種命名方式c++來鏈結函式的,所以上面的程式是找不著對應的add函式的。這個時候,extern "c"就有用了,我們在c++檔案中這樣宣告:

extern 「c」 int add(int x,int y);

就不會出現上面那種錯誤了。

extern 「c」的作用就是告訴編譯器,這是用c的方式寫成的庫檔案,請用c的方式來鏈結它。c和c++對函式的處理方式是不同的.extern "c"是使c++能夠呼叫c寫作的庫檔案的乙個手段,如果要對編譯器提示使用c的方式來處理函式的話,那麼就要使用extern "c"來說明。

下面給出問題的正確答案,以做參考。

c語言不支援函式過載,c++支援函式過載,函式被c++編譯後在庫中的名字與c語言的不同。假設某個函式的原型:void foo(int x,int y);該函式被c編譯器編譯後在庫中的名字為_foo,而c++編譯器則會產生像_foo_int _int之類的名字。c++提供了c鏈結交換指定符號extern"c"來解決名字匹配問題。

看下面這段**:

#includeusing namespace std;

extern int add(int, int);

float add(float a,float b)

int add(int a, int b)

int main()

在呼叫函式時,編譯器怎麼知道呼叫哪個函式呢?這是因為函式過載機制,在程式編譯時,編譯器會對函式做一些處理,對函式名相同的函式進行「重新命名」,如下:

我們可以看到,兩個函式的名字並不是相同的,編譯器在呼叫函式時根據引數,返回值來獲取呼叫物件。

add@@yahhh@z:@@ya表示起始,hhh表示引數引數返回值,h代表int型別,m代表float型別,@z重新命名結束。

當然,不同的編譯器重新命名的方式也是不同的(可以檢視相應的呼叫約定),了解在這個過程中發生了什麼事就可以了。

extern C 與函式過載

如果向要在乙個檔案中使用另乙個檔案中的變數,不能在標頭檔案中定義全域性變數,因為被多個檔案包含後會導致編譯出錯,並且靜態的static變數,只能在本檔案內使用,這時候就可以使用extern關鍵字。首先還是先看一下 extern 關鍵字的作用 extern關鍵字可以置於變數或函式前,以標示變數或函式的...

命名空間 預設引數 函式過載 extern C

2.預設引數 3.函式過載 4.extern c c 中的類和庫中有大量的關鍵字,那麼我們定義變數的時候就很容易與這些系統關鍵字發生衝突,使用命名空間的目的就是為了避免與關鍵字發生衝突 舉個簡單的例子,有人來學校找乙個叫張三的人,廣播出去後有非常多叫張三,這樣就導致了混淆,不知道你要找誰。但是你如果...

函式過載的實現機制

函式過載是一種特殊情況,c 允許在同一作用域中宣告幾個類似的同名函式,這些同名函式的形參列表 引數個數,型別,順序 必須不同,常用來處理實現功能類似資料型別不同的問題。為了實現函式過載的功能,函式名就不能再作為乙個函式的唯一標識,而是使用了name mangling方法將函式名轉化為了乙個獨一無二的...