C++ extern 的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ extern 的问题相关的知识,希望对你有一定的参考价值。

在学C++ extern 的时候.一个头文件A,和一个源文件B.源文件里在不加extern的时候,也可以访问头文件的对象!那extern的意义是什么?请举例说明!

  extern 表示其后面接的变量或者函数"需要导出"或者"是一个外部的变量或函数"。

  如果有头文件已经声明(采用函数或变量声明的方式),可以无需该关键字

  该关键字是告知编译器,其后面的声明函数或变量来自本文件的外部,最后链接的时候再定位。

  经典的应用场景在动态库导出或者外部变量引入。

  下面是一个动态库导出的示例:

extern "C" int dllfunc();//以C函数接口的方式导出函数dllfunc

  这样编译器在编译代码的时候,就会保留dllfunc的名称信息,方便其他模块调用此函数

  下面是一个外部变量引入的示例:

extern int g_total;//g_total是一个外部的整型变量

  这样编译器在编译本代码的时候,并不会立刻定位g_total的实体位置,而是推迟到link阶段去解决实体位置问题。

  对于函数引用声明,使用extern和不使用,在语法角度上没有本质区别。但是使用extern的函数,其名称信息为保留在生成好的目标文件中,可以被任何第三方使用者看到。

  因此,如果不是有意将其作为接口,请不要使用该关键字,以免影响模块的安全性

  对于变量,则必须要此关键字才能引用外部的变量,否则编译器会在此文件内声明一个同样名称的变量,并可能引发编译错误(同一名称空间中存在两个相同名称的变量)

参考技术A 首先,引用百度百科中extern关键字的解释:
【extern可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。另外,extern也可用来进行链接指定。】
我们只探讨前半部分,即【extern可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义】

假设你在头文件中声明了全局变量int global;,include了该头文件的cpp文件确实可以访问,前提是【只有一个cpp文件include了该头文件】,如果多个源文件中都包含了该头文件,这样的代码是【无法编译通过的】,编译器会报错:找到一个或多个多重定义的符号

报错原因简单来讲可以理解成:【每个cpp文件include的头文件,都等于是写在这个cpp里的代码】,如果是函数、类的声明则没问题(因为声明只说明了原型),但如果是定义(例如你的全局变量global)就会提示多重定义------这时编译器会认为你在两个cpp里分别定义了两个int global,而不是你想象的只有一个int global。

所以,综上所述,如果想在多个cpp中访问同一个全局变量,你的设想是行不通的,这时就要使用extern了。extern的作用是声明一个变量(前提是楼主需要理解声明和定义的区别),并且说明该变量的定义是在其他cpp文件中的,但真实的定义,必须还存在于某个cpp中(下面会说怎么做)。

所以,解决该问题的步骤如下:
1.在头文件中声明extern int global;
2.让所有需要访问该变量的cpp都包含该头文件
3.在任意一个cpp中中定义global(int global;)本回答被提问者采纳
参考技术B 指明是扩展变量。
fileA:
#include <stdio.h>
extern void hello(void);

fileB:
#include "fileA"
void hello(void)printf("Hello, world!");//可以不用再次include<stdio.h>

主要用于大项目的头文件。
举个例子,gnugo的头文件gnugo.h:
/* public functions */
extern void count(int i,
int j,
int color);

extern void countlib(int m,
int n,
int color);

extern void endgame(void);

extern void eval(int color);

extern void examboard(int color);

extern int getij(char move[],
int *i,
int *j);

extern unsigned int findcolor(int i,
int j);
....................

您可以在 C++ 中将指针声明为 extern 吗?

【中文标题】您可以在 C++ 中将指针声明为 extern 吗?【英文标题】:Can you declare a pointer as extern in C++? 【发布时间】:2008-12-14 03:34:15 【问题描述】:

我有以下无法编译的遗留 C++ 代码:

#include <stdio.h>
#include <iostream>

extern ostream *debug;

GCC (g++) 抱怨:“'*' 标记之前的预期初始化程序”

环顾四周,将这些声明为外部引用似乎更常见,如下所示:

extern ostream& debug;

为什么指针无效,但引用在这种情况下?

解决方案:

如下所述,真正的问题是缺少 std:: 命名空间说明符。显然,这在较旧的 C++ 代码中很常见。

【问题讨论】:

不确定这是否是一个正确的回应,但我认为 Visual Studio 可以处理这种事情。 您可能会发现“旧 C++ 代码”需要使用无法识别或不强制命名空间的编译器进行编译。 【参考方案1】:

是的,您可以使用 extern 声明一个指针。您的错误很可能是您忘记使用std:: 进行限定:

// note the header is cstdio in C++. stdio.h is deprecated
#include <cstdio>
#include <iostream>

extern std::ostream *debug;

【讨论】:

啊,是的,标准 C++ 库并不总是需要命名空间。 是的。那是 C++ 成为标准之前的时间。您曾经包含 iostream.h ,并使用 ostream 而不对其进行限定。但是现在,c++ 是一个标准,它要求你使用 std:: :)

以上是关于C++ extern 的问题的主要内容,如果未能解决你的问题,请参考以下文章

探讨下c++的声明和定义问题,关于extern

在 c++ 对象上使用 extern 时未定义的引用,但不是整数类型

(C++) 如何将 stl 列表声明为 extern?

从 C++ 链接到 C 库:为啥不总是需要 extern?

C++ C extern关键字详解 EntryPointNotFoundException处理

C++ Unresolved External Symbols Embedded Lua(基于 longjmp 问题)(不重复)