#ifdef标志告诉gcc和g ++编译器之间的区别?

时间:2014-09-18 18:27:05

标签: c++ c gcc compilation g++

gcc将C程序编译为C,将C ++程序编译为C ++,因此需要在C ++中使用“extern”C“'声明。然而,g ++将C程序编译为C ++,将C ++程序编译为C ++,因此要求'extern“C”'声明不得在C ++中使用。

检查没有任何输入的标准标志,

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

给出相同的结果。

__GNUG__       is equivalent to testing (__GNUC__ && __cplusplus)

同样将gcc与C ++源代码清单中的g ++ 区分开来

的魔力是什么?
#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 ++系统进行编译和链接,并要求Charlie的头文件中没有外部的“C”定义,否则它会拒绝链接。大型遗留系统“Bravo”主要用C语言编写,带有一点点C ++,并且还使用了用C ++编写的相同遗留源包Charlie。它使用gcc系统进行编译和链接,并要求Charlie的头文件中必须包含extern“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”'教条时,整个软件包拒绝链接。是的,还有其他方法来攻击一般问题,但这是一个简单的问题。这样的旗帜是存在的,还是已知不存在,或者答案是不确定的。我不知道,我自己。

1 个答案:

答案 0 :(得分:5)

标准技术是检查是否定义了预处理器符号__cplusplus

#ifdef __cplusplus
extern "C" {
#endif

/* declarations here */

#ifdef __cplusplus
}
#endif