extern“C”---当*正好*使用?

时间:2013-12-23 06:16:13

标签: c++

如果您想将此问题标记为重复,请注意我已阅读有关此主题的问题,但我仍不清楚。我的印象是,当包含C头并使用C代码链接时使用此构造(如果我错了,请纠正我)。这是否意味着在不处理目标文件时我永远不必使用“extern C”?如果我错了,为什么旧​​C代码不能编译为C ++,因为它最有可能是合法的c ++代码?

我对它有点不确定因为我发誓我在C ++中使用旧的C 源代码时遇到过这种情况,其中链接器错误仅通过“extern C”和库来解决标题确实有

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

他们周围。

编辑:很抱歉不清楚,但我想问的是,只有在包含C头并链接到预先存在的C对象文件时才需要“extern C”吗?如果它是真的,(并且它似乎从下面的评论来判断),为什么库标题周围有“extern C”子句,为什么它们不能被包含并编译为C ++?

4 个答案:

答案 0 :(得分:5)

C的{p> Name mangling规则不同.C和C可以有不同的ABI。单独这些原因要求您在C ++代码中嵌入C代码时使用extern "C"。即使编译器可以编译C和C ++代码,它也可能对这两种语言使用不同的名称修改规则或ABI。

此外,你的断言“[C代码最有可能......合法的c ++代码”并不完全正确,因为C和C ++随着岁月的流逝而越来越分散。他们有很多相似之处,但他们也有很多不同之处。

答案 1 :(得分: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。

答案 2 :(得分: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,它正在尝试解析,匹配定义的符号foo in C对象文件。

希望有所帮助。

答案 3 :(得分:0)

还有另一个案例尚未提及。 extern "C"指定C链接,但C不是唯一的其他语言。 C链接也被其他语言使用,这些语言过于模糊,没有自己广泛接受的联系。例如。 Java也使用C链接。显然你不能用C ++编译那个Java代码,所以你需要在C ++端extern "C"