繁体   English   中英

用于变量的 extern 和 extern “C”

[英]extern and extern “C” for variables

我正在编写一个 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只是告诉编译器下一个变量(全局)可能尚未声明,但它在不同的翻译单元中被声明为全局,并且在链接阶段,符号“全局”将与内存中的一个区域相关联.

正如一些人所评论的, 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”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM