2014-09-18 158 views
1

gcc將C程序編譯爲C和C++程序,因此需要在C++中聲明'extern「C」'。然而,g ++將C程序編譯爲C++,將C++程序編譯爲C++,因此要求在C++中不要使用'extern「C」'聲明。#ifdef標誌告訴gcc和g ++編譯器之間的區別?

檢查標準標誌沒有任何輸入,無論是

g++ -E -dM - </dev/null 
gcc -E -dM - </dev/null 

給出了相同的結果。

__GNUG__  is equivalent to testing (__GNUC__ && __cplusplus) 

這再次將從克++ 一個C++源內不分化的gcc上市

什麼是魔術

#ifndef __MAGIC_G++_INCLUDE_FLAG_BUT_NOT_GCC__ 

到環繞的extern 「C」{聲明?謝謝。

編輯:我知道這是一個相當深奧的情況。該測試需要在編譯器上完成,而不是源代碼的風味。在這兩種情況下,測試都在C++源代碼列表中執行(這就是爲什麼我提到GNUG不合適)。爲了澄清,測試main.cpp中

#include <iostream> 
int 
main(int argc, char **argv) 
{ 
#ifdef __cplusplus <<<< FIX THIS ONE 
    std::cout << "I was compiled using g++" << std::endl; 
#else 
    std::cout << "I was compiled using gcc" << std::endl; 
#endif 
} 

與時任

g++ main.cpp 

或在這兩種情況下

gcc main.cpp -lstdc++ 

,它似乎不正確地給作爲輸出「我整理是用g ++編譯的「。所以看起來cplusplus不是在這種情況下使用的正確標誌。我錯了嗎?或者什麼是正確的標誌?

編輯2: 謝謝,夥計們。這是你的一個例子。大型遺留系統「Alpha」主要以C語言編寫,帶有一點C++,並使用C++編寫的大型遺留源代碼包「Charlie」。它使用g ++系統進行編譯和鏈接,並要求查理的頭文件中沒有外部「C」定義,否則拒絕鏈接。大型遺留系統「Bravo」主要以C編寫,帶有一點C++,並且使用與C++編寫的相同的傳統源代碼包Charlie。它使用gcc系統進行編譯和鏈接,並要求查理的頭文件必須具有外部「C」定義,否則拒絕鏈接。新系統「Delta」,「Echo」和「Foxtrot」也想重用Charlie的部分源代碼,編譯器的使用是不確定的。正確的答案是徹底破解查理的標題,一勞永逸,用

#ifndef __MAGIC_G++_INCLUDE_FLAG_BUT_NOT_GCC__ 
extern "C" { 
#endif 
... 
declarations of code 
... 
#ifndef __MAGIC_G++_INCLUDE_FLAG_BUT_NOT_GCC__ 
} 
#endif 

然後用它做。否則總會有鏈接問題。是的,當然可以在這種特殊情況下編譯兩套庫,一套在C下,另一套在C++協議下,然後規定你應該使用這個特定的庫來處理這種特殊的鏈接。或者我可以想出兩套標題。在這個例子中,這兩者中的任何一個都不夠優雅,並且會繼續引發問題;還有其他的情況。至於g ++和gcc在底層使用同一個編譯器的評論,所以它不可能很重要,可悲的是,它確實如此。當包含錯誤的'extern'C''教條時,整個程序包拒絕鏈接。是的,還有其他方法可以攻擊一般問題,但這是一個簡單的問題。要麼存在這樣的旗幟,要麼已知它不存在,或者答案不明確。我不知道,我自己。

+0

有一個原因,你需要知道的?你的構建腳本/過程/等等。不是gcc/g ++編譯器的標準嗎? – sedavidw 2014-09-18 18:29:40

+3

您應該使用'gcc'命令編譯C源文件,'g ++'命令編譯C++源文件。你有這樣的理由嗎? – 2014-09-18 18:32:26

+0

'__cplusplus'是爲C++定義的,但不適用於C語言。無論如何,兩個驅動程序('gcc'和'g ++'都是真正編譯器的包裝器)都可以用來編譯C和C++源代碼,儘管它們默認使用不同的標誌,最適合於C和C++。 – Deduplicator 2014-09-18 18:33:11

回答

4

的標準方法是檢查預處理符號__cplusplus定義:

#ifdef __cplusplus 
extern "C" { 
#endif 

/* declarations here */ 

#ifdef __cplusplus 
} 
#endif 
+0

遺憾的是,這並未解決問題,請參閱編輯。謝謝。 – DragonLord 2014-09-18 19:58:54

+0

這是一種標準的第一順序方法,用於填充C代碼,使其適合C或C++,gcc下。它看起來不像它解決了我正在攻擊的C++問題。 – DragonLord 2014-09-19 04:25:26

+0

當源代碼是C而不是C++時,它能夠正確地分辨兩個編譯器之間的區別。也就是說,如果我使用main.c而不使用main.cpp,該標誌將會告訴gcc和g ++之間的區別。但是,由於extern「C」指令僅在C++中有用,因此尚不清楚這是如何解決一般問題的。 – DragonLord 2014-09-19 04:29:30