2013-12-23 50 views
1

如果您試圖將此問題標記爲重複,請注意,我已閱讀有關此主題的問題,但仍有一些問題尚未解決。我的印象是這個構造在包含C頭文件和使用C代碼鏈接時使用(請糾正我,如果我錯了)。這是否意味着在不處理目標文件時,我從不必使用「extern C」?如果我錯了,爲什麼舊​​的C代碼不能編譯爲C++,因爲它很可能是合法的C++代碼?extern「C」--- when * exactly * to use?

我有點玄乎它,因爲我發誓我已經下與舊的C 源代碼工作時,有情況++其中一個鏈接錯誤只與「外部C」,和庫頭解決確實有

#ifdef __cplusplus 
#extern "C"{ 
#endif 
//...... 
#ifdef _cplusplus 
} 
#endif 

圍繞着它們。

編輯:對不起,因爲不清楚,但我要問的是,只有在包含C頭文件和與預先存在的C對象文件鏈接時才需要「extern C」?如果這是真的(似乎是從下面的評論來判斷),爲什麼庫標題在它們周圍有「extern C」子句,爲什麼它們不能被包含和編譯爲C++?

+1

「爲什麼不能將舊的C代碼編譯爲C++?」即使C代碼是有效的C++,「extern C」也意味着鏈接到編譯爲C的目標文件,這意味着您仍然需要使用基於C的調用約定。 –

+0

@ChrisHayes所以當我不使用預先存在的對象文件時是這樣,我不需要「extern C」? – user3109672

+0

只是爲了使其明確(我仍然看到一個近距離投票):其他問題涵蓋了「如果連接到C代碼**是否需要**」extern「C」',這個問題是「是'extern」C 「只有**鏈接到C代碼時,才需要**」。請僅關注**,如果**。 – MSalters

回答

5

Name mangling C的規則是不同的,C可以有不同於C++的ABI。單獨這些原因要求您在C代碼中嵌入C代碼時使用extern "C"。即使編譯器可以編譯C和C++代碼,它也可以爲這兩種語言使用不同的名稱修改規則或ABI。另外,您斷言「[C代碼最有可能......合法C++代碼」並不完全正確,因爲隨着時間的推移,C和C++已經越來越多地分化了。他們有很多相似之處,但他們也有很多差異。

+0

抱歉,不明確。請參閱上面的編輯,謝謝 – user3109672

+0

還要注意,不同的C++編譯器以及過去甚至不同版本的相同編譯器都使用了不同的名稱約束約定。所以對於一個C++程序來說,它的功能定義爲「extrn」是非常常見的,因此它可以被使用不同C++編譯器的調用程序使用。 –

+1

@ user3109672:已更新。即使同一個編譯器編譯C代碼和C++代碼,它也可能有不同的做法(它可能有兩種模式,一種是「C模式」和一種在它們之間切換的「C++模式」,每種模式都有不同的規則)。 – Cornstalks

0

這實質上是在這裏找到答案:When to use extern "C" in simple words?

但相關的一點是,在C++編譯時,函數的名稱是「錯位」約功能(如參數類型)的某些信息進行編碼。由於C++總是以同樣的方式破壞函數名稱,所以在錯誤的名稱調用和放置在目標文件中的內容之間的所有內容都是一致的。

如果你用C語言編譯一個名爲「foo」的文件,並且在你的C++文件中有extern foo(int c);,那麼C++編譯會將「foo」改成不同的東西,例如foo__Ic(我剛剛編譯完成,實際的損壞看起來不同)。同時,在用C編譯器編譯的普通C代碼中,目標代碼定義了簡單的符號foo

然而,當整個事情是鏈接的,C++代碼中有一個外部符號foo__Ic,它正試圖解決,這確實不匹配的C對象文件中定義的符號foo

希望有所幫助。

1

庫本身是一個C對象文件,因此爲了使用它,您的應用程序必須期望一個C-ABI來調用庫中的函數,並且您需要在編譯時爲編譯器提供適當的提示功能。

extern void libraryFunc(); 

如果庫實際上是編譯爲C,這是它可以支持C C++的唯一途徑,那麼你需要包括C++編譯器,這必須與爲C.

註釋
#ifdef __cplusplus // only true when compiling with a C++ compiler 
extern "C" { 
#endif 
extern void libraryFunc(); 
#ifdef __cplusplus 
}; 
#endif 

向C編譯器,這個讀取

extern void libraryFunc(); 

向C++編譯器,這個讀取

extern "C" { 
extern void libraryFunc(); 

這相當於

extern "C" void libraryFunc(); 

編譯器和鏈接現在知道試圖調用/鏈接功能時,使用C ABI。

0

還有另一個案件尚未提及。 extern "C"指定C鏈接,但C不是唯一的其他語言。 C連接也被其他語言使用,這些語言太模糊不清,並且沒有被廣泛接受。例如。 Java也使用C鏈接。很明顯,你不能用C++編譯這個Java代碼,所以你在C++端需要extern "C"