C ++中extern“C”的效果是什么?
把extern "C"
放到C ++代码中究竟做了什么?
例如:
extern "C" {
void foo();
}
extern“C”使C ++中的函数名具有'C'链接(编译器不会破坏名称),以便客户端C代码可以使用'C'兼容头文件链接到(即使用)您的函数,该文件仅包含你的函数声明。 您的函数定义包含在二进制格式中(由C ++编译器编译),客户端的“C”链接器将使用“C”名称链接到该格式。
由于C ++重载了函数名,而C没有,C ++编译器不能仅仅使用函数名作为唯一的id来链接,所以它通过添加关于参数的信息来破坏名称。 由于不能重载C中的函数名,因此AC编译器不需要对名称进行重新命名。当您声明函数在C ++中具有外部“C”链接时,C ++编译器不会将参数/参数类型信息添加到用于连锁。
大家知道,你可以明确地为每个单独的声明/定义指定“C”链接,或者使用一个块将一系列声明/定义分组,以具有特定的链接:
extern "C" void foo(int);
extern "C"
{
void g(char);
int i;
}
如果您关心技术问题,那么它们将在C ++ 03标准的第7.5节中列出,这里是一个简短的摘要(重点在于extern“C”):
只是想添加一些信息,因为我还没有看到它发布。
你会经常在C头文件中看到代码,如下所示:
#ifdef __cplusplus
extern "C" {
#endif
// all of your legacy C code here
#ifdef __cplusplus
}
#endif
这实现的目的是它允许你在你的C ++代码中使用这个C头文件,因为宏“__cplusplus”将被定义。 但是,您仍然可以将其与遗留的C代码一起使用,因为它没有定义宏,所以它不会看到独特的C ++构造。
虽然,我也看到了C ++代码,例如:
extern "C" {
#include "legacy_C_header.h"
}
我想象的是完成了很多相同的事情。
不知道哪种方式更好,但我都看到了。
在每个C ++程序中,所有非静态函数都以二进制文件的形式表示为符号。 这些符号是用于唯一标识程序中某个功能的特殊文本字符串。
在C中,符号名称与函数名称相同。 这是可能的,因为在C中没有两个非静态函数可以具有相同的名称。
由于C ++允许重载,并且具有很多C不具备的功能,比如类,成员函数,异常规范,所以不能简单地使用函数名称作为符号名称。 为了解决这个问题,C ++使用所谓的名称修改,它将函数名和所有必要的信息(比如参数的数量和大小)转换成仅由编译器和链接器处理的奇怪外观字符串。
因此,如果您将函数指定为extern C,则编译器不会执行名称修改,并且可以使用其符号名称作为函数名称直接访问它。
这在使用dlsym()
和dlopen()
来调用这些函数时非常方便。