“外部人员声明”;";全局变量 在C和C++中,如果我想在其他编译单元中使用全局变量,我将定义变量如下: int g_myVal = 0;
这将为“外部人员声明”;";全局变量 在C和C++中,如果我想在其他编译单元中使用全局变量,我将定义变量如下: int g_myVal = 0;,c++,C++,这将为int分配存储 然后在头文件中声明变量: extern int g_myVal; 这会通知编译器该符号存在于其他编译单元中。然后由链接器解析符号 但是,如果我希望变量可以与“C”链接一起使用,我必须定义变量(分配存储),如下所示: 那么,如何区分分配存储和仅仅通知编译器该符号存在于另一个编译单元中呢?您的混淆源于这样一个事实:extern和extern“C”做两件不同的事情 关于extern extern本身就是一个存储类说明符: [C++11:7.1.1/6]:外部说明符只能应用于变
int
分配存储
然后在头文件中声明变量:
extern int g_myVal;
这会通知编译器该符号存在于其他编译单元中。然后由链接器解析符号
但是,如果我希望变量可以与“C”链接一起使用,我必须定义变量(分配存储),如下所示:
那么,如何区分分配存储和仅仅通知编译器该符号存在于另一个编译单元中呢?您的混淆源于这样一个事实:
extern
和extern“C”
做两件不同的事情
关于
extern
extern
本身就是一个存储类说明符:
[C++11:7.1.1/6]:
外部说明符只能应用于变量和函数的名称。extern
说明符不能用于声明类成员或函数参数。有关使用extern
说明符声明的名称的链接,请参见3.5。[注意:关键字extern
也可用于显式实例化和链接规范,但在此类上下文中它不是存储类说明符。-结束注意]
关于
extern“C”
正如尾随注释所提到的,还有另一个上下文,您可以在其中使用extern
关键字作为链接说明符:
<> >代码[C++11:7.5/2 ]:使用链接规范实现:< /COD> C++与非C++代码片段之间的链接(3.5):
连杆规格:extern
string literal{
声明seqopt}
extern
字符串文字声明
C++喜欢重复使用关键字
声明与定义 现在,默认情况下,用链接说明符标记的变量是一个声明而不是一个定义,因此在这个意义上,就好像您还使用了
extern
的其他含义一样:
[C++11:7.5/7]:
链接规范中直接包含的声明被视为包含extern
说明符(7.1.1),以确定声明名称的链接以及它是否是定义。此类声明不应指定存储类别。[示例:
-[结束示例]
正如您在上面的示例中所看到的,在使用链接说明符时,仍然可以使用声明或定义
下面是另一个例子:
// Everything in this block has C linkage
extern "C" {
// Declaration of g_myVal
extern int g_myVal;
// Definition of g_myVal2
int g_myVal2;
}
int main()
{
g_myVal2 = 5; // ok
g_myVal = 6; // not okay - linker error, symbol not found
}
当你添加一个初始化器。。。 话虽如此,将
g_myVal
作为声明的处理被推翻,因为您使用了初始值设定器,这迫使声明成为一个定义:
[C++11:7/8]:
除了在声明的一般形式中找到的语法组件之外,还将这些语法组件添加到函数声明中,以生成函数定义但是,对象声明也是一个定义,除非它包含extern
说明符并且没有初始值设定项(3.1)。定义会导致保留适当的存储量,并执行任何适当的初始化(8.5)
我希望这能澄清您的代码中发生了什么,以及
extern
的不同含义。在本例中,将初始值设定项=0
更改为定义,这就是为什么在此处分配存储。(即使只是简单的extern
也会发生同样的情况)声明不应该是extern int g_myVal
?@jbgs:g_myVal的extern
是多余的。@user2485710:不,不是。@user2485710:另一个翻译单元与它有什么关系?我提供了一个现场演示以及标准引用,它们都说了同样的话:extern
绝对不是多余的。它在很大程度上改变了声明的含义。@user2485710:噢,你是指原始代码中的g_myVal
,即带有初始值设定项的代码吗?是的,这是多余的,因为语句是一个定义,因为它有一个初始化器。这是真的。但不是另一种说法,我的回答中也没有,标准中的例子中也没有。
extern "C" double f();
static double f(); // error
extern "C" int i; // declaration
extern "C" {
int i; // definition
}
extern "C" static void g(); // error
// Everything in this block has C linkage
extern "C" {
// Declaration of g_myVal
extern int g_myVal;
// Definition of g_myVal2
int g_myVal2;
}
int main()
{
g_myVal2 = 5; // ok
g_myVal = 6; // not okay - linker error, symbol not found
}