[英]extern and extern “C” for variables
我正在编写一个 C++ 共享库供 C 程序使用。 但是,我有一个关于extern
和extern "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.