我正在学习编程语言课程,我们正在谈论 extern "C" 宣言。

除了“ IT接口C和C ++”以外,该声明如何在更深层次的水平上起作用?这也如何影响程序中发生的绑定?

有帮助吗?

解决方案

extern "C" 用于确保以下符号不是 陷入困境 (装饰)。


例子:

假设我们在一个名为的文件中有以下代码 test.cpp:

extern "C" {
  int foo() {
    return 1;
  }
}

int bar() {
  return 1;
}

如果您运行 gcc -c test.cpp -o test.o

看一下符号名称:

00000010 T _Z3BARV

00000000 t foo

foo() 保持名称。

其他提示

让我们看一下可以在C和C ++中编译的典型函数:

int Add (int a, int b)
{
    return a+b;
}

现在在C中,该函数在内部被称为“ _ADD”。而C ++函数使用称为“ m-Mangling”的系统在内部完全不同。它基本上是一种命名函数的方法,因此具有不同参数的相同函数具有不同的内部名称。

因此,如果在add.c中定义了add(),并且如果尝试将add.h添加到c ++文件中,则在add.h中具有原型。因为C ++代码正在寻找一个与add.c中的名称不同的函数,您将获得链接器错误。要解决这个问题,您必须通过以下方法包括add.c:

extern "C"
{
#include "add.h"
}

现在,C ++代码将与_ADD链接,而不是C ++名称被操纵版本。

这是表达式的用途之一。最重要的是,如果您需要在C ++程序中严格编译C代码(通过Include语句或其他一些方式),则需要用外部“ C” {...}声明包装它。

当您标记带有外部“ C”的代码块时,您会告诉系统使用C样式链接。

这主要影响着链接器的名称。您没有使用C ++样式的名称熔断(支持操作员过载更为复杂),而是从链接器中获得标准的C风格命名。

在C ++中,函数的名称/符号实际上被重命名为其他内容,以使不同的类/名称空间可以具有相同签名的函数。在C中,这些功能都是全球定义的,不需要这种自定义的重命名过程。

为了使C ++和C相互交谈,“ Extern C”指示编译器不要使用C约定。

应当指出的是 extern "C" 还修改功能的类型。它不仅会在较低级别上修改事物:

extern "C" typedef void (*function_ptr_t)();

void foo();

int main() { function_ptr_t fptr = &foo; } // error!

类型 &foo 不等于Typedef指定的类型(尽管代码被某些但并非所有编译器都接受)。

外部C影响C ++编译器的名称。它是使C ++编译器不伪装名称的一种方式,或者以与C编译器相同的方式进行操作。这就是它接口C和C ++的方式。

举个例子:

extern "C" void foo(int i);

将允许在C模块中实现该函数,但可以从C ++模块调用它。

当试图使C模块调用C ++功能(显然C无法使用C ++类)时,问题出现。 C编译器不喜欢 extern "C".

因此,您需要使用此信息:

#ifdef __cplusplus
extern "C" {
#endif

void foo(int i);

#ifdef __cplusplus
}
#endif

现在,当这出现在标题文件中时,C和C ++编译器都会对声明感到满意,现在可以在C或C ++模块中定义它,并且可以通过C和C ++代码调用。

外部“ c”表示封闭的代码使用C风格的链接和名称杂交。 C ++使用更复杂的名称杂交格式。这是一个例子:

http://en.wikipedia.org/wiki/name_mangling

int example(int alpha, char beta);

在C中: _example

在C ++中: __Z7exampleic

更新:正如Gmannickg在评论中指出的那样,名称杂交的模式取决于编译器。

extern“ c”,是用C绑定声明函数的关键字,因为C编译器和C ++编译器会将源转化为对象文件中的不同形式:

例如,代码段如下:

int _cdecl func1(void) {return 0}
int _stdcall func2(int) {return 0}
int _fastcall func3(void) {return 1}

32位C编译器将以以下形式翻译代码:

_func1
_func2@4
@func3@4

在CDECL中,func1将翻译为'_姓名'

在stdcall中,func2将翻译为'_name@x'

在FastCall中,Func2将翻译为'@name@x'

'X'是指参数列表中参数的多少个字节。

Windows上的64位约定没有领先的下消息

在C ++中,引入了类,模板,名称空间和运算符过载,因为不允许使用相同名称的两个函数,C ++编译器在符号名称中提供类型信息,

例如,代码段如下:

int func(void) {return 1;}
int func(int) {return 0;}
int func_call(void) {int m=func(), n=func(0);}

C ++编译器将如下翻译代码:

int func_v(void) {return 1;}
int func_i(int) {return 0;}
int func_call(void) {int m=_func_v(), n=_func_i(0);}

'_v'和'_i'是“ void”和“ int”的类型信息

这是MSDN的报价

“ Extern关键字声明变量或函数,并指定其具有外部链接(其名称可以从已定义的文件以外的其他文件中可见)。修改变量时,Extern指定该变量具有静态持续时间(已分配了静态持续时间(已分配当程序开始并在程序结束时进行处理时)。变量或函数可以在另一个源文件中或以后在同一文件中定义。默认情况下,文件范围的变量和函数声明是外部的。”

http://msdn.microsoft.com/en-us/library/0603949d%28vs.80%29.aspx

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top