C++ extern“C“詳談
阿新 • • 發佈:2022-03-07
C++語言在編譯的時候為了解決函式的多型問題,建立了與C語言編譯器不同的函式名修飾規則,C++語言在編譯的時候會將函式名和引數聯合起來生成一箇中間的函式名稱,而C語言則不會,因此會造成連結階段無法找到對應函式的情況。因此,C函式就需要用extern “C”進行連結指定,通知編譯器以下函式或檔案中函式是C語言函式,編譯時按照C語言編譯器的函式名修飾規則,保持函式的名稱,不回生成用於連結的中間函式名。
C語言編譯器的函式名修飾規則
對於__stdcall呼叫約定,編譯器和連結器會在輸出函式名前加上一個下劃線字首,函式名後面加上一個“@”符號和其引數的位元組數。比如 :_functionname@number。
1 int add(char a,char b);
C語言編譯器修飾後的名稱為
1 _add@2
C++語言編譯器的函式名修飾規則
C語言編譯器的函式名修飾規則僅僅使用函式名對不同函式進行區分,不同過載函式會出現修飾輸出名稱一致的情況,為了解決函式的多型問題,C++語言編譯器建立了一套更加複雜的函式名修飾規則,但資訊更充分,通過分析修飾名不僅可以知道函式的呼叫方式。返回值型別,引數個數甚至引數型別。
對於__stdcall方式,引數表的開始標識是“@@YG”,引數表的拼寫代號如下表所示:
X--void | D--char |
E--unsigned char | F--short |
H--int | I--unsigned int |
J--long | K--unsigned long |
M--float | N--double |
_N--bool | U--struct |
PA--指標 |
PB--const 指標... |
詳見
1 int show(char *var1,unsigned long);
C++語言編譯器修飾後的名稱為
?show@@YGHPADK@Z
此外,extern"C"是C++的語法,通常我們寫一個頭檔案時,並不確定是在C或C++編譯器環境下使用,如果在C語言編譯器下使用extern"C"時,編譯器會報錯。因此,使用extern"C"需要進行編譯器進行檢查:
1 #ifdef __cpluscplus 2 extern "C" { 3 #endif 4 5 //some code 6 7 #ifdef __cplusplus 8 } 9 #endif