c++中关于extern的理解

众所周知 extern是表示声明的关键字
extern int i;/*这是声明*/
int i;/*这是定义*/


 

虽然有人觉得第二行也是声明,但是根据c++ primer的说法,下面的确实是定义,因为这个时候i会被分配内存,而且声明是不会分配内存的。由分不分配内存作为声明和定义的判断标准的话,第二行确实是定义。

 

当然有的时候声明后也可以立即定义,如

extern int i = 1;/*这是声明+定义*/

 

在函数外部使用extern的时候,会非常容易。不过在函数内部使用extern(或许这样没什么意义),则会遇到很多让人迷惑的地方。

如下列代码:

void main()
{
    extern int i;
    i = 1;
}


 

乍一看觉得这样的代码没什么问题,先声明,然后再定义,很正确。但是这样实际上是错误的,会报一个重定义的错误(redefinition)。

误认为这段代码正确的原因可能是这样:很多人觉得先声明后定义是一件很正常的事情,然而这却不一定。这里有个概念模糊,确切的声明是形如下列代码的

extern int i;

 


而形如下列代码的,不是声明

 

int i;
extern int i = 1;


我们常说的先声明后定义,是指的这样的情况

int i;
i = 1;



 

但这其实是错误的概念。因为“int i;”这样的语句并不是声明,而是定义。

与上面这种误解恰恰相反,在使用extern作为声明的时候,其实声明往往出现在定义之后,而且应该出现在定义之后

举个例子,在函数外部写如下声明代码

extern int i;


通常是在别的源文件中定义好了i后,才会写这样一句声明,表明要用的i来自别的文件,而且是已经被定义好的i

而绝对不会先如上声明一次,然后在自己的源文件中又定义一次i(因为这样是多此一举)。所以说,声明往往是在定义之后的。

也就是说,见到了某个对象(如int i)的exten声明,往往代表i是已经被定义好了的。

也就是说,在效果上,声明≈定义。见到了某个对象的extern声明,代表这个对象已经被定义好了,就可以直接对其赋值或用其进行运算(当然之前要确保它是被初始化了的)。

理解了上面的,就能理解在函数体内怎么使用extern了。也能明白下面的代码错在哪了。

void main()
{
    extern int i;
    int i = 1;
}


 


因为extern int i;相当于指明某处已经定义过一个i了,接下来又要int i = 1;这显然是重定义了。

改成这样就是没问题的:


void main()
{
    extern int i;
    i = 1;
}


 


不过要注意,在适合的地方要确切存在i的定义

那么何谓适合的地方

我们知道通常c++的作用域是被大括号括起来的,最外层没有被括起来的地方,是最大的作用域,在这里定义的变量是全局变量,可以被任何地方访问。当然访问不是没有限制的,其中一种方法就是通过extern声明。在程序的任何地方,只要是用extern声明了一个全局变量,那这个全局变量就变得可以访问了。因为全局变量的作用域是整个程序。也就是说,最外层没有被括号括起来的地方,是存在定义的适合的地方。

实际上,只有最外层才是适合的地方,因为extern其实只能声明全局变量。下面的代码就是错误的,因为i是局部变量。extern int i会试图找寻一个已经被定义的全局变量i,但是却没找到,所以会出现fatal error LNK1120: 1 unresolved externals (无法连接的外部变量)的错误。


 

int main()
{
 int i = 1;
	{	
		extern int i;
		cout<<i;
	}
	return 0;
}


 下面的代码是正确的

int i = 3;

int main()
{
 int i = 1;
	{
		
		extern int i;
		cout<<i;
	}
	return 0;
}

而且输出的是3

代码改为为下面这样的话,输出的是1,原因是定义域。extern相当于在当前定义域中定义了一个变量,在这个定义域的外部是看不到这个变量的。

int i = 3;

int main()
{
 int i = 1;
	{
		
		extern int i;
		cout<<i;
	}
	cout<<i;
	return 0;
}


 

 

体会这几个例子,就能明白extern的一些特点。

1、使用于定义之后

2、只用于外部变量(即全局变量)

3、遵从普通变量的定义域划分规则
......

 

 

水平有限,又是特别仓促写的东西,有点不好理解请多包涵,有错误欢迎指正

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值