C ++中extern“ C”的做用是什么?

extern "C"放入C ++代码到底能作什么? c#

例如: 函数

extern "C" {
   void foo();
}

#1楼

extern“ C”旨在由C ++编译器识别,并通知编译器所注明的功能已(或将要)以C样式进行编译。 这样,在连接时,它会连接到C中正确版本的函数。 布局


#2楼

它通知C ++编译器在连接时以C样式查找这些函数的名称,由于在连接阶段,用C和C ++编译的函数的名称不一样。 spa


#3楼

它以一种可从C调用该函数的方式更改函数的连接。实际上,这意味着函数名称不会被修饰code


#4楼

extern“ C”使C ++中的函数名称具备'C'连接(编译器不会更更名称),以便客户端C代码可使用'C'兼容的头文件连接到(即便用)您的函数,该头文件仅包含函数的声明。 函数定义以二进制格式(由C ++编译器编译)包含,客户端“ C”连接器随后将使用“ C”名称连接至该二进制文件。 对象

因为C ++具备重载的函数名,而C没有重载,所以C ++编译器不能仅使用函数名做为要连接的惟一ID,所以它经过添加有关自变量的信息来破坏名称。 AC编译器不须要处理名称,由于您不能在C中重载函数名称。当您声明函数在C ++中具备外部“ C”连接时,C ++编译器不会将参数/参数类型信息添加到用于连锁。 ip

众所周知,您能够显式地为每一个单独的声明/定义指定“ C”连接,也可使用一个块对一系列声明/定义进行分组以具备必定的连接: 字符串

extern "C" void foo(int);
extern "C"
{
   void g(char);
   int i;
}

若是您关心技术方面的问题,它们会在C ++ 03标准的7.5节中列出,此处是一个简短的摘要(着重于外部“ C”): get

  • extern“ C”是一个连接规范
  • 每一个编译器都须要提供“ C”连接
  • 连接规范应仅在命名空间范围内发生
  • 全部函数类型,函数名称和变量名称都具备语言连接。 请参阅Richard的注释:只有具备外部连接的函数名称和变量名称才具备语言连接。
  • 即便语言相同,具备不一样语言连接的两个函数类型也都是不一样类型
  • 连接规格嵌套,内部决定最终的连接
  • 类成员忽略外部“ C”
  • 最多一个具备特定名称的函数能够具备“ C”连接(不管名称空间如何)
  • extern“ C”强制函数具备外部连接(不能使其静态) 请参见Richard的评论: 'extern“ C”'内部的'static'有效; 如此声明的实体具备内部连接,所以没有语言连接
  • 从C ++到其余语言定义的对象以及从其余语言到C ++定义的对象的连接是实现定义的和语言相关的。 只有两种语言实现的对象布局策略足够类似时,才能实现这种连接

#5楼

在每一个C ++程序中,全部非静态函数在二进制文件中均以符号表示。 这些符号是特殊的文本字符串,可惟一标识程序中的功能。 编译器

在C语言中,符号名称与函数名称相同。 这是可能的,由于在C中,没有两个非静态函数能够具备相同的名称。

因为C ++容许重载,而且具备C所不容许的许多功能(例如类,成员函数,异常规范),所以没法简单地将函数名用做符号名。 为了解决这个问题,C ++使用了所谓的名称修饰,将函数名称和全部必要的信息(例如参数的数量和大小)转换为一些仅由编译器和连接器处理的怪异字符串。

所以,若是将函数指定为extern C,则编译器不会对其进行名称修饰,而且可使用其符号名做为函数名称直接对其进行访问。

这在使用dlsym()dlopen()调用此类函数时很是方便。

相关文章
相关标签/搜索