外部"C"全局变量的外部声明

dor*_*ron 4 c++

在C和C++中,如果我想在其他编译单元中使用全局变量,我将定义变量,如:

int g_myVal = 0;
Run Code Online (Sandbox Code Playgroud)

这为int.分配存储空间.

在头文件中,我然后声明变量:

extern int g_myVal;
Run Code Online (Sandbox Code Playgroud)

这通知编译器所述符号存在于某些其他编译单元中.然后由链接器来解析符号.

但是,如果我希望变量可以与"C"链接一起使用,我必须定义变量(分配存储),如:

extern "C" int g_myVal = 0;
Run Code Online (Sandbox Code Playgroud)

那么如何区分分配存储并告知编译器所述符号存在于另一个编译单元中?

Lig*_*ica 8

你的困惑的事实,茎externextern "C"做是两回事.


关于 extern

extern它本身就是一个存储类说明符:

[C++11: 7.1.1/6]:extern说明符只能应用到的变量和函数的名称.的extern说明符不能在类成员或函数参数的声明被使用.有关使用extern说明符声明的名称的链接,请参见3.5.[注: extern关键字也可以使用显式实例化联动的规格,但它不是一个存储类说明符在这样的背景下. - 尾注]


关于 extern "C"

正如该尾随说明所暗示的,还有另一个上下文,您可以使用该extern关键字作为链接说明符:

[C++11: 7.5/2]:使用链接规范可以实现C++和非C++代码片段之间的链接(3.5):

linkage-specification:
    extern string-literal { declaration-seq opt }
    extern string-literal declaration

C++喜欢重用关键字.


声明与定义

现在,默认情况下,标记有链接说明符的变量是声明而不是定义,因此从这个意义上来说,就好像您还使用了其他含义extern:

[C++11: 7.5/7]:直接包含在链接规范中的声明被视为包含说明extern符(7.1.1),以确定声明的名称的链接以及它是否是定义.此类声明不应指定存储类.[例如:

extern "C" double f();
static double f(); // error
extern "C" int i; // declaration
extern "C" {
   int i; // definition
}
extern "C" static void g(); // error
Run Code Online (Sandbox Code Playgroud)

- 结束例子]

正如您在上面的示例中所看到的,当您使用链接说明符时,仍然可以使用声明或定义.

这是另一个例子:

// 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
}
Run Code Online (Sandbox Code Playgroud)

现场演示


添加初始化程序时...

尽管如此,通过使用初始化器来推翻g_myVal作为声明的处理,这迫使声明成为一个定义:

[C++11: 7/8]:除了在一般声明形式中找到的语法组件之外,还将语法组件添加到函数声明中以生成函数定义.但是,对象声明也是一个定义,除非它包含说明extern符并且没有初始值设定项(3.1).定义导致保留适当的存储量并进行任何适当的初始化(8.5).

我希望这能澄清你的代码中具有这些不同含义的内容extern.