4 回答

TA貢獻1859條經驗 獲得超6個贊
extern“C”使得C ++中的函數名稱具有“C”鏈接(編譯器不會破壞名稱),以便客戶端C代碼可以使用僅包含“C”兼容頭文件來鏈接(即使用)您的函數。聲明你的功能。您的函數定義包含在二進制格式(由C ++編譯器編譯)中,客戶端“C”鏈接器將使用“C”名稱鏈接到該格式。
由于C ++有函數名稱的重載而C沒有,所以C ++編譯器不能只使用函數名作為鏈接的唯一id,因此它通過添加有關參數的信息來破壞名稱。AC編譯器不需要破壞名稱,因為您不能在C中重載函數名。當您聲明函數在C ++中具有extern“C”鏈接時,C ++編譯器不會將參數/參數類型信息添加到用于的名稱連鎖。
您知道,您可以明確指定每個單獨的聲明/定義的“C”鏈接,或使用塊將一系列聲明/定義分組以具有特定的鏈接:
extern "C" void foo(int);extern "C"{ void g(char); int i;}
如果您關心技術細節,它們列在C ++ 03標準的7.5節中,這里是一個簡短的摘要(重點是extern“C”):
extern“C”是一個鏈接規范
每個編譯器都需要提供“C”鏈接
鏈接規范只應在命名空間范圍內發生
所有函數類型,函數名和變量名都有語言鏈接 請參閱Richard的注釋:只有具有外部鏈接的函數名和變量名具有語言鏈接
具有不同語言鏈接的兩種函數類型是不同的類型,即使它們是相同的
連接規格嵌套,內部確定最終的連接
類成員忽略extern“C”
最多一個具有特定名稱的函數可以具有“C”鏈接(無論命名空間如何)
extern“C”強制函數具有外部鏈接(不能使其靜止) 請參閱Richard的注釋:'static'在'extern'中“C”'有效; 如此聲明的實體具有內部鏈接,因此沒有語言鏈接
從C ++到在其他語言中定義的對象以及從其他語言在C ++中定義的對象的鏈接是實現定義的和語言相關的。只有在兩種語言實現的對象布局策略足夠相似的情況下才能實現這種聯系

TA貢獻1786條經驗 獲得超13個贊
只是想添加一些信息,因為我還沒有看到它發布。
您經常會在C標頭中看到代碼,如下所示:
#ifdef __cplusplusextern "C" {#endif// all of your legacy C code here#ifdef __cplusplus}#endif
這實現了它允許您將C頭文件與C ++代碼一起使用,因為將定義宏“__cplusplus”。但是你可以也仍然使用舊的C代碼,其中宏使用NOT定義,所以它不會看到獨特的C ++構建。
雖然,我也看過C ++代碼,例如:
extern "C" {#include "legacy_C_header.h"}
我想象的完成了同樣的事情。
不確定哪種方式更好,但我已經看到了兩種方式。

TA貢獻1772條經驗 獲得超5個贊
在每個C ++程序中,所有非靜態函數都在二進制文件中表示為符號。這些符號是特殊文本字符串,用于唯一標識程序中的函數。
在C中,符號名稱與函數名稱相同。這是可能的,因為在C中沒有兩個非靜態函數可以具有相同的名稱。
因為C ++允許重載并且具有C不具備的許多功能 - 比如類,成員函數,異常規范 - 所以不可能簡單地使用函數名作為符號名。為了解決這個問題,C ++使用了所謂的名稱修改,它將函數名稱和所有必要信息(如參數的數量和大?。┺D換為僅由編譯器和鏈接器處理的奇怪字符串。
因此,如果您將函數指定為extern C,則編譯器不會對其執行名稱修改,并且可以使用其符號名稱作為函數名稱直接訪問它。
這在使用dlsym()
和dlopen()
調用此類函數時非常方便。
- 4 回答
- 0 關注
- 718 瀏覽
添加回答
舉報