鏈結指示符extern C

2021-05-08 10:02:15 字數 1585 閱讀 6499

程式設計師用鏈結指示符linkage directive 告訴編譯器該函式是用其他的程式語言

編寫的鏈結指示符有兩種形式既可以是單一語句single statement 形式也可以是復

合語句compound statement 形式

// 單一語句形式的鏈結指示符

extern "c" void exit(int);

// 復合語句形式的鏈結指示符

extern "c"

// 復合語句形式的鏈結指示符

extern "c"

被extern "c"修飾的變數和函式是按照c語言方式編譯和連線的;

未加extern 「c」宣告時的編譯方式

首先看看c++中對類似c的函式是怎樣編譯的。

作為一種物件導向的語言,c++支援函式過載,而過程式語言c則不支援。函式被c++編譯後在符號庫中的名字與c語言的不同。例如,假設某個函式的原型為:

void foo( int x, int y );

該函式被c編譯器編譯後在符號庫中的名字為_foo,而c++編譯器則會產生像_foo_int_int之類的名字(不同的編譯器可能生成的名字不同,但是都採用了相同的機制,生成的新名字稱為「mangled name」)。

foo_int_int這樣的名字包含了函式名、函式引數數量及型別資訊,c++就是靠這種機制來實現函式過載的。例如,在c++中,函式void foo( int x, int y )與void foo( int x, float y )編譯生成的符號是不相同的,後者為_foo_int_float。

同樣地,c++中的變數除支援區域性變數外,還支援類成員變數和全域性變數。使用者所編寫程式的類成員變數可能與全域性變數同名,我們以"."來區分。而本質上,編譯器在進行編譯時,與函式的處理相似,也為類中的變數取了乙個獨一無二的名字,這個名字與使用者程式中同名的全域性變數名字不同。

未加extern "c"宣告時的連線方式

假設在c++中,模組a的標頭檔案如下:

// 模組a標頭檔案 modulea.h

#ifndef module_a_h

#define module_a_h

int foo( int x, int y );

#endif

在模組b中引用該函式:

// 模組b實現檔案 moduleb.cpp

#include "modulea.h"

foo(2,3);

實際上,在連線階段,聯結器會從模組a生成的目標檔案modulea.obj中尋找_foo_int_int這樣的符號!

加extern "c"宣告後的編譯和連線方式

加extern "c"宣告後,模組a的標頭檔案變為:

// 模組a標頭檔案 modulea.h

#ifndef module_a_h

#define module_a_h

extern "c" int foo( int x, int y );

#endif

在模組b的實現檔案中仍然呼叫foo( 2,3 ),其結果是:

(1)模組a編譯生成foo的目標**時,沒有對其名字進行特殊處理,採用了c語言的方式;

(2)聯結器在為模組b的目標**尋找foo(2,3)呼叫時,尋找的是未經修改的符號名_foo。

cpp 鏈結指示

extern 如果現在有乙個c靜態庫和相應的標頭檔案,內含函式void eat int,int 在c靜態庫中用彙編 表示為 sub eat ret如果c 鏈結器去link這個函式的時候,按照c 處理函式的規則,去link子過程 sub eat int int 顯然找不到,報link error,為了...

替代鏈結 extern 「C」

ifndef account h define account h ifdef cplusplus 下邊的設計就是無論是c 或者 c 都可以直接的呼叫,只需要加上此標頭檔案就可以,extern c endif endiffloat f int a,int b void p void t includ...

C decltype型別指示符

有些情況下,我們希望從表示式的型別推斷出要定義的變數的型別,但是不想用該表示式的值初始化變數。此時就要用到c 11引入的第二種型別說明符delctype,它的作用就是選擇並返回運算元的資料型別。編譯器分析表示式並得到它的型別,但不實際計算表示式的值 decltype size 5 s i declt...