extern和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" 。 这是为什么? 这对我来说不直观。

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

通过将extern "C"附加到您的C ++声明(对象和函数等),您可以为它们提供“C链接” – 使它们可以从C代码访问。 如果省略此“语言链接”规范,编译器不会做任何正确的链接。 在函数的情况下,由于重整,这导致链接失败。 在全局变量的情况下,一切都可以正常工作,因为变量不需要修改。

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

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

然而,当我查看包含dumpbin实用程序的global定义的已编译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" – 如果它是函数或全局变量则无关紧要。 如果它是一个全局变量,它可能无论如何都可以工作,但它不能保证(并且可能是危险的)。

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

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

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

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

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