Daily-C-Study(5):C语言extern关键字

Daily-C-Study(5):C语言extern关键字

成于坚持,败于止步

extern,外面的、外来的意思。那它有什么作用呢?举个例子:假设你在大街上看到一个黑皮肤绿眼睛红头发的美女(外星人?)或者帅哥。你的第一反应就是这人不是国产的。extern 就相当于他们的这些区别于中国人的特性。

extern 可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,下面的代码用到的这些变量或函数是外来的,不是本文件定义的,提示编译器遇到此变量和函数时在其他模块中寻找其定义。就好比在本文件中给这些外来的变量或函数带了顶帽子,告诉本文件中所有代码,这些家伙不是本地人。

extern 修饰的变量或函数的三种形式:

1. extern修饰变量的声明。

举例来说,如果文件a.c需要引用b.c中变量int v,就可以在a.c中声明extern int v,然后就可以引用变量v.这里需要注意的是,被引用的变量v的链接属性必须是外链接(external)的,也就是说a.c要引用到v,不只是取决于在a.c中声明extern int v,还取决于变量v本身是能够被引用到的。这涉及到c语言的另外一个话题--变量的作用域。能够被其他模块以extern修饰符引用到的变量通常是全局变量。还有很重要的一点是,extern int v可以放在a.c中的任何地方,比如你可以在a.c中的函数fun定义的开头处声明extern int v,然后就可以引用到变量v了,只不过这样只能在函数fun作用域中引用v罢了,这还是变量作用域的问题。对于这一点来说,很多人使用的时候都心存顾虑。好像extern声明只能用于文件作用域似的。

2. extern修饰函数声明。

从本质上来讲,变量和函数没有区别。函数名是指向函数二进制块开头处的指针。如果文件a.c需要引用b.c中的函数,比如在b.c中原型是int fun(int mu),那么就可以在a.c中声明extern int fun(int mu),然后就能使用fun来做任何事情。就像变量的声明一样,extern int fun(int mu)可以放在a.c中任何地方,而不一定非要放在a.c的文件作用域的范围中。 对其他模块中函数的引用,最常用的方法是包含这些函数声明的头文件。使用extern和包含头文件来引用函数有什么区别呢?extern的引用方式比包含头文件要简洁得多!extern的使用方法是直接了当的,想引用哪个函数就用extern声明哪个函数。这大概是KISS原则的一种体现吧!这样做的一个明显的好处是,会加速程序的编译(确切的说是预处理)的过程,节省时间。在大型C程序编译过程中,这种差异是非常明显的。

3. 此外,extern修饰符可用于指示C或者C++函数的调用规范。

比如在C++中调用C库函数,就需要在C++程序中用extern "C"声明要引用的函数。这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。主要原因是C++和C程序编译完成后在目标代码中命名规则不同。

下面依次来说几个例子:

1.在同一个文件内声明的外部变量

#include <stdio.h>
int max(int x,int y); //函数提前声明
int main(int argc,char *argv[ ] )
{
	int result;
	extern int X; //外部变量声明
	extern int Y;
	result = max(X,Y);
	printf("the max value is %dn",result);
	return 0;
}
int X = 10; //定义外部变量
int Y = 20;
int max(int x, int y)
{
	return (x>y ? x : y);
}
这种用法基本上是画蛇添足,直接就过吧

2.在不同文件中声明的外部变量

假设a.c的内容如下:

#include <stdio.h>
extern int a;							//外部变量提前声明
extern int exe(int x); //外部函数提前声明
int main(int argc, char *agrv[])
{
	printf("%dn",exe(a));
	return 0;
}
则b.c的内容如下:
#include <stdio.h>
int BASE=2; //变量定义
int a=10;
int exe(int x)
{
	int i;
	int ret=1;
	for(i=0;i<x;i++)
	{
		ret*=BASE;
	}
	return ret;
}

在b.c文件中定义a=10和exe函数,在a.c中引用a时,需要用extern关键字声明其为外部变量,同样的,在a.c中引用exe函数时也需要用extern关键字声明其为外部函数,否则编译会找不到该变量。

对于多个文件的工程,可以采用这种方法来操作。实际工程中,对于模块化的程序文件,在其文件中可以预先留好外部变量的接口,也就是只采用extern声明变量,不定义变量,也通常在模块程序的头文件中声明,在使用该模块时,只需要在使用时定义一下即可,如上述a.c文件,做好相应的函数接口,留好需要改变a值的声明,在需要使用该模块时,只需要在调用的文件中定义具体的值即可。

引用外部变量和通过函数形参值传递变量的区别:用extern引用外部变量,可以在引用的模块内修改其值,而形参值传递的变量则不能修改其值,除非是地址传递。因此,如果多个文件同时对需要应用的的变量进行同时操作,可能会修改该变量,类似于形参的地址传递,从而影响其他模块的使用,因此,要慎重使用。

(1) extern 变量名

在任何函数体外声明或定义变量时,不加extern可能是定义也可能是声明,编译器选择初始化的那个(最多一个地方对他进行了初始化),如果没有初始化则任选其中一个作为定义,其他为声明,但是加extern肯定是声明; 如果不想让其它源文件链接到,则需要使用static关键字;在函数体内声明(注意是声明,在函数体内部不能定义外部变量)使用其他源文件中定义的变量时,必须使用extern关键字,因为在函数体内默认为局部变量。

(2) extern 函数

函数默认是外部的(在函数体内或函数体外声明一个外部函数,extern关键字均可省略),如果不想让其它源文件链接到,在函数前static关键字虽然在很多情况下extern关键字是可省的,但是为了提高程序的可读性,还是加上它比较好.

就先到这里,O(∩_∩)O~

我的专栏地址:http://blog.csdn.net/column/details/c-daily-study.html

待续。。。。。。

你可能感兴趣的:(c)