爲何要使用extern "C"

C/C++採用的是分別編譯模型, 源代碼只要聲明函數, 就可調用。函數

編譯時,在函數調用處生成一個符號引用。spa

連接時,將函數調用處的符號引用,替換成地址(甚至仍有可能繼續保留符號, 載入時再計算地址)。翻譯

因此, 如下二者必須徹底比配, 不然連接時會出錯。
code

1. 函數調用處引用的符號名編譯器

2. 函數定義處公開的符號名編譯

如何使得二者匹配?
class

不管是在調用處仍是在定義處, 不管是C仍是C++(注1), 編譯器都會對函數名進行mangling, 產生一個符號名。引用

而 extern "C" 就是通知C++編譯器(注2), 將某函數按照C的規則進行mangling, 產生符號名。di

若是是在聲明處使用 extern "C", 函數調用處引用的符號名將按C的mangling規則產生。co

若是是在定義處使用 extern "C", 翻譯單元裏公開的符號名將按C的mangling規則產生。

同時, C編譯器將 extern "C" 視爲錯誤—— 因此須要相似的代碼

#ifdef __cplusplus
extern "C" {
#endif 

/*...*/ 

#ifdef __cplusplus
}
#endif

extern "C" 一般使用的地方。

1. 當一個函數已經由C編譯器實現

在一個C++翻譯單元中, 必須使用 extern "C" 聲明改函數。

這樣, 該函數調用產生的符號名引用和已經由C編譯器實現的函數的符號名才能匹配。

2. 用C++編譯器實現C和C++均可調用的函數。

本身聲明extern 「C」。 在C++翻譯單元中, 該函數名按C規則修飾以後, 獲得符號名, 並公開。

C++的調用者依然須要使用 extern "C" 來聲明。

C的調用者直接聲明。

目的也是爲了使得引用與實現的符號名匹配。

相關文章
相關標籤/搜索