首页 理论教育C语言程序设计基础:变量作用域解析

C语言程序设计基础:变量作用域解析

【摘要】:局部变量的作用域被限定在它们所定义的范围之内。局部变量在函数调用时的特征示例。图5.11全局变量与局部变量作用域重叠示意图在这种全局变量与局部变量作用域重叠的情况下,当程序的控制流程进入这个作用域重叠区域时必须要确定应该使用哪一个同名的变量。

变量的作用域与变量的定义位置有关,根据定义位置上将变量分为“全局变量”和“局部变量”两类。

1.全局变量

所谓全局变量,是指定义在C程序中所有函数之外的变量,全局变量也称为外部变量。C程序中全局变量的作用域(作用范围)从其在源程序文件中定义处开始到其所在的源程序文件结束为止。C语言中全局变量定义的一般形式如下:

[extern]<数据类型符>变量表;在全局变量的定义形式中,关键字extern是全局变量默认的存储类型,在定义全局变量时一般将其省略。如果对于全局变量使用了关键字extern,目的是对程序中定义的全局变量进行重新声明以扩充其作用域,这种声明方法的意义和使用方法将在后面予以讨论。

在定义全局变量时,也可以对其进行初始化工作。如果在定义全局变量时没有显式初始化,编译系统会自动将其初始化为0(若是字符类数据则初始化为'\0')。

【例5.12】 全局变量的作用域示例(为了讨论方便加上行号)。

程序在第5行定义了整型变量x,由于变量x定义在所有函数的外面,所以变量x是全局变量,其作用范围(作用域)从第5行开始至第21行结束。同时由于定义全局变量x时没有对其进行初始化,因而全局变量x的初始值为0。程序执行时,在主函数(第8行)对全局变量x实施了增一的操作,使得变量x的值为1;然后在第9行调用函数increa,在函数increa中对全局变量x实施了x+=5的操作,使得变量x的值为6;其后又调用了函数increb,在函数increb中对全局变量x实施了x-=2的操作,使得变量x的值为4;所以该程序运行的结果为:x=4。

2.局部变量

所谓局部变量是指定义在函数内部的变量,局部变量默认情况下也称为自动变量。局部变量的作用域被限定在它们所定义的范围之内。在C程序中定义局部变量的地方有3个,它们是:①函数形式参数表部分;②函数体内部;③复合语句内部。C语言中局部变量定义的一般形式如下:

[auto]<数据类型符>变量表;局部变量的存储类别符是auto,由于auto类型符是局部变量默认的存储类型,所以在变量的定义中一般将该关键字省略。同样,在C程序中定义局部变量的同时也可对其进行初始化工作,如果定义局部变量时没有对其进行显式的初始化则局部变量的初始值是随机的数值。

自动变量的建立和撤销都是系统自动进行的,如在某个函数中定义了自动变量,只有当这个函数被调用时系统才会为这些局部变量分配存储单元;当函数执行完毕,程序控制流程离开这个函数时,自动变量被系统自动撤销,其所占据的存储单元被系统自动收回。由此可以得出关于局部变量的两个非常重要的结论:

①C函数中同一组局部变量(自动变量)的值在该函数的任意两次调用之间不会保留,即函数的每次调用都是使用的不同局部变量组。

【例5.13】 局部变量在函数调用时的特征示例。

例5.13程序的函数incre在第一次被调用时,会创建局部变量x并赋初值为20,然后对其进行加5的操作并将结果25返回到主函数中输出(注意:随着函数执行完成后控制流程的返回,函数中定义的局部变量x被系统自动撤销)。当函数incre第二次被调用时,会重新创建局部变量x并赋初值为20,然后对其进行加5的操作并将结果25返回到主函数中输出,所以程序执行的结果为:

x=25

x=25

②C程序中,定义在不同局部范围内的局部变量之间是毫无关系的,即使它们的名字相同亦是如此。

【例5.14】 编写程序输出如图所示的字符图形,见图5.10(每行15个星号,共输出5行)。

图5.10 例5.14 字符图形

上面程序中,虽然在两个函数中都定义了名字为i的变量,但由于它们是定义在各自函数内部的,所以它们都是局部变量,这些局部变量的作用范围(作用域)被限制在它们定义所处的函数内部,即两个在不同函数中定义的局部变量i的作用域是互不相交的,因而在两个不同函数中定义的同名变量之间是毫无关系的。在上面程序中,两个用于控制循环的循环变量i都能够按照自己的规律变化,所以程序能够得到正确的结果。

3.全局变量与局部变量作用域重叠问题(www.chuimin.cn)

在C程序中,全局变量与局部变量的作用域有可能出现重叠的情形。即在某些特定的情况下,可能会出现全局变量、在函数内部定义的局部变量乃至于在复合语句中定义的局部变量名字相同的现象,这样在程序中的某些区域内势必会出现若干个同名变量都起作用的情形,如图5.11所示。

图5.11 全局变量与局部变量作用域重叠示意图

在这种全局变量与局部变量作用域重叠的情况下,当程序的控制流程进入这个作用域重叠区域时必须要确定应该使用哪一个同名的变量。C语言中规定按“定义就近原则”来确定使用的变量,具体说就是如下两条原则:

①在函数中如果定义有与全局变量同名的局部变量,则当程序的控制流程进入到函数作用范围时,程序使用在函数内部(包括形式参数表和函数体)定义的局部同名变量。

②在程序的一个更小局部范围(复合语句)中如果定义有与较大范围(函数局部或全局)变量同名的变量,则当程序的控制流程进入到这个小的(复合语句)局部范围时,使用在该小局部范围内所定义的局部同名变量。

在图5.11中,在标注为①的程序区域内,全局变量x、函数中定义的变量x以及复合语句中定义的变量x都起作用,当程序的控制流程进入该区域时,使用的是在复合语句中定义的变量x;在标注为②的区域中除去标注为①区域的剩余部分,全局变量x、函数中定义的变量x都起作用,当程序的控制流程进入该区域时,使用的是在函数中定义的变量x;在标注为③的源程序文件其余地方(除去②所占据区域),程序使用的是全局变量x。

【例5.15】 全局变量与局部变量作用域重叠时使用变量示例。

上面程序在主函数之前、主函数中以及在主函数内部的复合语句中都定义了整型变量x。在程序的执行过程中,首先执行了复合语句中的printf("复合语句中:x=%d\n",x);语句,虽然在此区域中全局变量x、主函数开始部分定义的局部变量x以及复合语句中定义的变量x都能够起作用,但按C语言的规定应该使用在复合语句中定义的变量x,所以程序在此输出结果:“复合语句中:x=20”;当程序执行到语句printf("主函数中:x=%d\n",x);时,由于在主函数中定义有与全局变量同名的变量x,按C语言规定因该使用在函数体开始处定义的变量x,所以程序在此输出结果:“主函数中:x=10”;程序在调用函数f1时执行语句printf("函数f1中:x=%d\n",x);,由于在函数f1中没有定义变量x,按C语言规定应该使用全局变量x,所以程序在此输出结果:“函数f1中:x=0”,注意函数输出x=0的原因是全局变量并没有初始化,编译系统将全局变量自动初始化为0值。综上所述,例3.15程序的执行结果为(注意输出顺序):

复合语句中:x=20

主函数中:x=10

函数f1中:x=0  /*全局变量x没有显式初始化,默认的初始化值为0*/