C ++中extern「 C」的做用是什麼?

extern "C"放入C ++代碼到底能作什麼? c#

例如: 函數

extern "C" {
   void foo();
}

#1樓

extern「 C」旨在由C ++編譯器識別,並通知編譯器所註明的功能已(或將要)以C樣式進行編譯。 這樣,在連接時,它會連接到C中正確版本的函數。 佈局


#2樓

它通知C ++編譯器在連接時以C樣式查找這些函數的名稱,由於在連接階段,用C和C ++編譯的函數的名稱不一樣。 spa


#3樓

它以一種可從C調用該函數的方式更改函數的連接。實際上,這意味着函數名稱不會被修飾code


#4樓

extern「 C」使C ++中的函數名稱具備'C'連接(編譯器不會更更名稱),以便客戶端C代碼可使用'C'兼容的頭文件連接到(即便用)您的函數,該頭文件僅包含函數的聲明。 函數定義以二進制格式(由C ++編譯器編譯)包含,客戶端「 C」連接器隨後將使用「 C」名稱連接至該二進制文件。 對象

因爲C ++具備重載的函數名,而C沒有重載,所以C ++編譯器不能僅使用函數名做爲要連接的惟一ID,所以它經過添加有關自變量的信息來破壞名稱。 AC編譯器不須要處理名稱,由於您不能在C中重載函數名稱。當您聲明函數在C ++中具備外部「 C」連接時,C ++編譯器不會將參數/參數類型信息添加到用於連鎖。 ip

衆所周知,您能夠顯式地爲每一個單獨的聲明/定義指定「 C」連接,也可使用一個塊對一系列聲明/定義進行分組以具備必定的連接: 字符串

extern "C" void foo(int);
extern "C"
{
   void g(char);
   int i;
}

若是您關心技術方面的問題,它們會在C ++ 03標準的7.5節中列出,此處是一個簡短的摘要(着重於外部「 C」): get

  • extern「 C」是一個連接規範
  • 每一個編譯器都須要提供「 C」連接
  • 連接規範應僅在命名空間範圍內發生
  • 全部函數類型,函數名稱和變量名稱都具備語言連接。 請參閱Richard的註釋:只有具備外部連接的函數名稱和變量名稱才具備語言連接。
  • 即便語言相同,具備不一樣語言連接的兩個函數類型也都是不一樣類型
  • 連接規格嵌套,內部決定最終的連接
  • 類成員忽略外部「 C」
  • 最多一個具備特定名稱的函數能夠具備「 C」連接(不管名稱空間如何)
  • extern「 C」強制函數具備外部連接(不能使其靜態) 請參見Richard的評論: 'extern「 C」'內部的'static'有效; 如此聲明的實體具備內部連接,所以沒有語言連接
  • 從C ++到其餘語言定義的對象以及從其餘語言到C ++定義的對象的連接是實現定義的和語言相關的。 只有兩種語言實現的對象佈局策略足夠類似時,才能實現這種連接

#5樓

在每一個C ++程序中,全部非靜態函數在二進制文件中均以符號表示。 這些符號是特殊的文本字符串,可惟一標識程序中的功能。 編譯器

在C語言中,符號名稱與函數名稱相同。 這是可能的,由於在C中,沒有兩個非靜態函數能夠具備相同的名稱。

因爲C ++容許重載,而且具備C所不容許的許多功能(例如類,成員函數,異常規範),所以沒法簡單地將函數名用做符號名。 爲了解決這個問題,C ++使用了所謂的名稱修飾,將函數名稱和全部必要的信息(例如參數的數量和大小)轉換爲一些僅由編譯器和連接器處理的怪異字符串。

所以,若是將函數指定爲extern C,則編譯器不會對其進行名稱修飾,而且可使用其符號名做爲函數名稱直接對其進行訪問。

這在使用dlsym()dlopen()調用此類函數時很是方便。

相關文章
相關標籤/搜索