我們經常在**中看到這樣的宣告:
#ifdef __cplusplus
extern
"c"#endif
其中#ifdef __cplusplus是用來判斷檔案是否為cpp檔案,這個很好理解,那被它限定的extern 「c」 又是什麼意思呢?其實這個extern 「c」 就是表達了兩個含義
(1)extern表示內宣告的函式和變數是外部變數和函式(見注釋1);
(2)「c」表示內的函式都是以c語言的形式編譯的,告訴編譯器要以c語言形式對{}的函式進行編譯(對實現檔案來說)或者以c語言的形式查詢函式(對引用這些函式的檔案來說)。
我們知道編譯器對c和c++檔案定義的函式在編譯時會按照一定規則來記錄函式的名字,由於c++允許過載,所以編譯後的函式名中一般會加上函式的引數型別用以區分不同的過載函式。而c沒有這樣的特性,這就造成了兩種檔案編譯後的函式名字不同,為了防止多人協作**現c、c++語言的不同造成的相容問題,一般要在函式的宣告處加上extern 「c」 來限定它用c語言編寫, 總之,函式的實現方式一定要和函式的查詢方式一致,是c都是c,c++就都是c++,以下是幾種使用情況說明:
(1)乙個程式中有三個檔案:main.cpp, func.h, func.cpp, func.h中用extern 「c」 限定了所有function,則在main和func.cpp中無論怎麼引用func.h都可以,加不加extern 「c」 都行,func.cpp會以c形式編譯
(2)main.cpp, func.h, func.cpp,三個檔案都沒有用extern 「c」 限定,編譯執行都沒有問題,因為function的編譯和main都是c++形式的,main中查詢function是用c++形式查詢的,沒有問題
(3)main.c, func.h, func.cpp, 這種情況必須在func.h中加extern 「c」 , 或者在func.cpp引用func.h的地方把func.h用extern 「c」 {}包起來,
extern
"c"
(4)main.cpp, func.h, func.c,這種情況必須在main.cpp中引用func.h是用extern 「c」 {}把func.h包起來
extern
"c"
最後請注意這樣書寫
extern
"c"
不要這樣寫
extern
"c"
注釋1:所謂外部函式和變數也就是全域性函式和變數,是在整個程式的各個檔案和so庫中的api都可見的函式和變數,比如在1.so中引用乙個標頭檔案,標頭檔案宣告乙個外部全域性函式extern void func(); 在主程式中同樣引用這個標頭檔案並在主程式的某個cpp檔案中實現它,那麼在執行過程中,1.so是可以找到並呼叫這個func()的。相反,在so中實現乙個extern 函式並宣告匯出(用.def檔案),在主程式中載入宣告的標頭檔案並引用鏈結這個so,在主程式中照樣能呼叫這個extern 函式。extern變數也是這樣。
注釋2,在所有函式外部宣告乙個函式或變數後,不加關鍵字extern時一般預設為全域性,想要宣告成本地函式和變數,則必須加static關鍵字限定為只在本檔案內可見。
關於注釋2需要注意的幾點:
(1)全域性變數指的是其生命週期是在整個程式執行的完整週期內的,並不是指這個變數定義好了之後就在各處都可見了,它仍然需要嚴格遵循作用域規則。例如在main函式之後定義乙個變數
int
main
(void
)int g_num =
11;
此時想要在main中使用這個g_num是不行的,因為不在它的作用域, 需要在使用之前增加 extern int g_num;或者int g_num; 這樣的宣告。
(2)定義在函式之後的全域性變數即使在函式內用extern宣告,其作用域也並不是全域性的,所以它不屬於global namespac的成員,不能使用全域性作用域運算子::來呼叫它,除非它的宣告或定義在main函式之上(可以在其他函式的定義或宣告之後,大家都是全域性的)。
注釋3:extern 「c++」 也是存在的哦
extern
"c++"
關於 extern C 的問題
extern c 多用在用非c的語言寫的程式意欲呼叫用c寫成的庫。用c寫成的庫里的函式名 肯定是由c編譯器編譯的 都是c的風格 也就是簡單的乙個函式名。比如函式void st read ft t f 在庫里的符號名就是st read。那麼在你的程式中 假設是c 寫成的 需要用到這個st read函式...
深入理解extern C
一 從c與c 編譯連線方式深入理解extern c 1 c和c 對函式的處理方式是不同的.被extern c 修飾的變數和函式是按照c語言方式編譯和連線的.extern c 用於實現c 與c及其它語言的混合程式設計。2 未加extern c 宣告時的編譯方式 首先看看c 中對類似c的函式是怎樣編譯的...
關於C 中的名字修飾以及 extern C
在c c 中,乙個程式要執行起來,需要經歷以下幾個階段 預處理,編譯,彙編,鏈結.而名字修飾是一種在編譯過程中,將函式,變數的名稱重新改變的機制,簡單來說就是編譯器為了區分各個函式,將函式通過某種演算法,重新修飾為乙個全域性唯一的名稱.在c語言當中的名字修飾規則非常簡單,只是在函式名字前面新增了下劃...