外部和外部" C"对于变量

时间:2016-07-01 09:06:52

标签: c++ c linkage extern-c

我正在为要使用的C程序编写C ++共享库。不过,我对externextern "C"提出了疑问。

考虑以下代码

我的头文件是这样的:

#ifdef __cplusplus      
     extern "C" int global;
     extern "C" int addnumbers(int a, int b); 
 #else
      extern int global;
 #endif

这完美无缺;我只需申报

int global;

在我的.cpp或我的.c文件中。但是,我不明白的是:

extern "C"extern之间的区别是什么?我试着评论extern "C" int global并且它有效!为什么?

我知道extern "C"用于建立C链接。这就是我extern "C" int addnumbers(int,int)的原因。换句话说,如果我想编写一个将在C程序中使用的C ++函数,我会编写extern "C"。现在,全球变量怎么样 - 我猜这里的情况有所不同?我希望C程序使用名为global的C ++变量,但我可以使用extern而不是extern "C"。这是为什么?这对我来说并不直观。

评论:我不认为这是重复的,因为我在询问当你将它用于变量与函数时有什么区别。

4 个答案:

答案 0 :(得分:9)

通过将extern "C"附加到您的C ++声明(对象和函数等),您可以给它们" C链接" - 使用C代码访问它们。如果省略这个"语言链接"规范,编译器没有做任何努力来做正确的链接。在函数的情况下,由于重整,这导致链接失败。在全局变量的情况下,一切都可能正常,因为变量不需要修改。

但是,在我的系统(MS Visual Studio)上,如果我忘记"那么C和C ++之间的联系就不起作用了。在C ++头文件中指定extern "C"链接规范。示例错误消息:

error LNK2001: unresolved external symbol "int global" (?_global)

然而,当我检查包含global实用程序dumpbin定义的已编译C ++源代码时,我看到了

00B 00000014 SECT4  notype       External     | ?global@@3HA (int global)

因此,MS Visual Studio会破坏全局变量的名称,除非它们具有C链接 - 这使得C链接规范成为必需。

此外,请考虑以下示例:

namespace example {
    int global;
}

如果全局变量在命名空间内,则C代码将无法访问它。在这种情况下,所有编译器都需要在C ++声明中使用正确的链接规范:

namespace example {
    extern "C" int global;
}

结论:

当您想要C链接时使用extern "C" - 如果它是函数或全局变量并不重要。如果它是一个全局变量,它可能无论如何都可以工作,但它不能保证(并且可能是危险的)。

答案 1 :(得分:2)

extern只是告诉编译器下一个变量(全局)可能尚未声明,但它在不同的转换单元中被声明为全局,并且在链接阶段,符号“global”将是与记忆中的一个区域相关联。

虽然正如一些人评论的那样,extern "C"用于解决C ++中名称修改的问题,但这个函数将被链接器称为addnumbers_i_i(或类似的东西),而在c中它的符号是addnumbers

答案 2 :(得分:0)

" C ++有一个特殊的关键字来声明一个带有C绑定的函数:extern" C"。声明为extern" C"使用函数名作为符号名,就像C函数一样。因此,只有非成员函数可以声明为extern" C",并且它们不能被重载。"

C ++中没有编译器生成的函数名称的标准。关键字extern" C"指示编译器在C标准中生成函数名。

答案 3 :(得分:0)

我发现extern“C”用于使用C标准编译的C ++函数,它不用变量,因为C和C ++中函数名的解决方案是不同的。例如“void foo(int x,int y)”,C编译器会将其转换为“_foo”,而C ++编译器会将其转换为“_foo_int_int”。