我正在为要使用的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"
。这是为什么?这对我来说并不直观。
评论:我不认为这是重复的,因为我在询问当你将它用于变量与函数时有什么区别。
答案 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”。