变量的外部和外部"C"

extern and extern "C" for variables

本文关键字:外部 变量      更新时间:2023-10-16

我正在写一个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;
}

结论:

使用extern "C"当你想要C链接-不管它是一个函数还是一个全局变量。如果它是一个全局变量,它可能会工作,但它不能保证(并且可能是危险的)。

extern只是告诉编译器下一个变量(global)可能还没有被声明,但它在另一个翻译单元中被声明为global,并且在链接阶段,符号"global"将与内存中的一个区域相关联。

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

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

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

我发现extern "C"是用来使c++函数在C标准中编译的,它不与变量有关,因为C和c++中函数名称的解决方案不同。如"void foo(int x, int y)", C编译器会将其翻译为"_foo",而c++编译器会将其翻译为"_foo_int_int"。