gcc编译C程序时将其视为C语言,编译C++程序时将其视为C++语言,因此需要在C++中使用'extern "C"'声明。而g++将C程序作为C++程序进行编译,将C++程序作为C++程序进行编译,因此在C++中不应使用'extern "C"'声明。
检查标准标志而没有任何输入时,两者是一样的。
g++ -E -dM - </dev/null
gcc -E -dM - </dev/null
产生相同的结果。
__GNUG__ is equivalent to testing (__GNUC__ && __cplusplus)
这句话的意思是,在 C++ 的源代码中,无法区分 gcc 和 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++
在这两种情况下,似乎都会错误地输出"I was compiled using g++"。因此,在这种情况下,cplusplus不是正确的标志。我错了吗?或者什么是正确的标志?
编辑2: 谢谢大家。这里有一个例子供您参考。大型遗留系统"Alpha"主要用C编写,少量使用C++,并使用大型遗留源包"Charlie",该源包用C++编写。它使用g++系统进行编译和链接,并要求Charlie的头文件中没有extern "C"定义,否则它将拒绝链接。大型遗留系统"Bravo"主要用C编写,少量使用C++,也使用相同的遗留源包Charlie,用C++编写。它使用gcc系统进行编译和链接,并要求Charlie的头文件必须有extern "C"定义,否则它将拒绝链接。新系统"Delta"、"Echo"和"Foxtrot"也希望重用来自Charlie的部分源代码,使用的编译器尚不确定。正确的答案是一劳永逸地修改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"'教条,整个软件包将无法链接。当然,还有其他解决这个一般性问题的方法,但这是个简单的问题。要么存在这样的标志,要么已知不存在,要么答案尚不确定。我自己也不知道。
gcc
命令来编译C语言源代码,使用g++
命令来编译C++语言源代码。你这么做有什么特别的原因吗? - Keith Thompson__cplusplus
定义了C++,但未定义 C。无论如何,两个驱动程序(gcc
和g++
都是真正编译器的包装器)都可以用于编译 C 和 C++ 源代码,尽管它们默认使用不同的标志,最适合分别用于 C 和 C++。 - Deduplicatormain.cpp
,无论你在命令行上调用g++
还是gcc
,都将使用g++
进行编译(在后一种情况下,gcc
只会为您调用g++
),因此您始终会得到“使用g++编译”。如果您想强制使用gcc而不考虑名称,可以使用命令行参数-x c
,但这样它将根本无法编译,因为它不是有效的C代码。 - Chris Dodd