程式設計師用鏈結指示符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...