4 回答
TA贡献1859条经验 获得超6个赞
extern“C”使得C ++中的函数名称具有“C”链接(编译器不会破坏名称),以便客户端C代码可以使用仅包含“C”兼容头文件来链接(即使用)您的函数。声明你的功能。您的函数定义包含在二进制格式(由C ++编译器编译)中,客户端“C”链接器将使用“C”名称链接到该格式。
由于C ++有函数名称的重载而C没有,所以C ++编译器不能只使用函数名作为链接的唯一id,因此它通过添加有关参数的信息来破坏名称。AC编译器不需要破坏名称,因为您不能在C中重载函数名。当您声明函数在C ++中具有extern“C”链接时,C ++编译器不会将参数/参数类型信息添加到用于的名称连锁。
您知道,您可以明确指定每个单独的声明/定义的“C”链接,或使用块将一系列声明/定义分组以具有特定的链接:
extern "C" void foo(int);extern "C"{ void g(char); int i;}
如果您关心技术细节,它们列在C ++ 03标准的7.5节中,这里是一个简短的摘要(重点是extern“C”):
extern“C”是一个链接规范
每个编译器都需要提供“C”链接
链接规范只应在命名空间范围内发生
所有函数类型,函数名和变量名都有语言链接 请参阅Richard的注释:只有具有外部链接的函数名和变量名具有语言链接
具有不同语言链接的两种函数类型是不同的类型,即使它们是相同的
连接规格嵌套,内部确定最终的连接
类成员忽略extern“C”
最多一个具有特定名称的函数可以具有“C”链接(无论命名空间如何)
extern“C”强制函数具有外部链接(不能使其静止) 请参阅Richard的注释:'static'在'extern'中“C”'有效; 如此声明的实体具有内部链接,因此没有语言链接
从C ++到在其他语言中定义的对象以及从其他语言在C ++中定义的对象的链接是实现定义的和语言相关的。只有在两种语言实现的对象布局策略足够相似的情况下才能实现这种联系
TA贡献1786条经验 获得超12个赞
只是想添加一些信息,因为我还没有看到它发布。
您经常会在C标头中看到代码,如下所示:
#ifdef __cplusplusextern "C" {#endif// all of your legacy C code here#ifdef __cplusplus}#endif
这实现了它允许您将C头文件与C ++代码一起使用,因为将定义宏“__cplusplus”。但是你可以也仍然使用旧的C代码,其中宏使用NOT定义,所以它不会看到独特的C ++构建。
虽然,我也看过C ++代码,例如:
extern "C" {#include "legacy_C_header.h"}
我想象的完成了同样的事情。
不确定哪种方式更好,但我已经看到了两种方式。
TA贡献1772条经验 获得超5个赞
在每个C ++程序中,所有非静态函数都在二进制文件中表示为符号。这些符号是特殊文本字符串,用于唯一标识程序中的函数。
在C中,符号名称与函数名称相同。这是可能的,因为在C中没有两个非静态函数可以具有相同的名称。
因为C ++允许重载并且具有C不具备的许多功能 - 比如类,成员函数,异常规范 - 所以不可能简单地使用函数名作为符号名。为了解决这个问题,C ++使用了所谓的名称修改,它将函数名称和所有必要信息(如参数的数量和大小)转换为仅由编译器和链接器处理的奇怪字符串。
因此,如果您将函数指定为extern C,则编译器不会对其执行名称修改,并且可以使用其符号名称作为函数名称直接访问它。
这在使用dlsym()
和dlopen()
调用此类函数时非常方便。
- 4 回答
- 0 关注
- 661 浏览
添加回答
举报