首页 > 编程笔记

C语言变量作用域(全局变量和局部变量)

变量根据声明的位置不同在程序执行过程中的作用范围也不同。

我们应该知道函数被调用前,该函数内的形参是不占用内存的存储单元的;调用以后,形参才被分配内存单元;函数调用结束,形参所占用的内存也将被回收,被释放。这一点说明形参只有在定义它的函数内才是有效的,离开该函数就不能再使用了。这个变量有效性的范围或者说该变量可以引用的范围,称为变量的作用域。

不仅仅是形参变量,C语言中所有的变量都有自己的作用域。变量按照作用域范围可分为两种,即局部变量和全局变量。

C语言局部变量

局部变量就是在函数内部或者块内定义的变量。局部变量只在定义它的函数内部或块内部有效,在这个范围之外是不能使用这些变量的。例如:

int func(int a,int b)                /*函数func()*/
{
   double x,y;
   …
}          
main()
{
   int m,n;
   …
}

在函数 func() 内定义了 4 个变量,a、b 为形参,x、y 为一般的变量。在 func() 的范围中,a、b、x、y 都有效,或者说 a、b、x、y 这 4 个变量在 func() 函数内是可见的。同理,m、n 的作用域仅限于 main() 函数内。

关于局部变量的作用域,还要说明以下几点。
  1. 主函数main()中定义的变量m、n只在主函数中有效,并没有因为在主函数中定义而在整个文件或程序中有效。因为主函数也是一个函数,它与其他函数是平行的关系。
  2. 不同的函数中可以使用相同的变量名,它们代表不同的变量,这些变量之间互不干扰。
  3. 在一个函数内部,还可以在复合语句(块)中定义变量,这些变量只在该复合语句中有效。
  4. 如果局部变量的有效范围有重叠,则有效范围小的优先。例如:

void main()
{
    int a,b,c;
    …
    {
       int c;
       c=a+b;
        …
    }
}

整个 main() 函数内 a、b、c 均有效,但函数内的复合语句中又定义了一个变量 c,此时的变量与复合语句外部的变量 c 重名,那么在复合语句范围内定义的变量 c 优先使用。

【示例1】 局部变量的应用。代码如下:
#include<stdio.h>
int main()
{
   int i=2,j=3,k;         /*变量i,j,k在main()函数内部均有效*/
   k=i+j;
   {
      int h=8;          /*变量h只在包含它的复合语句中有效*/
      printf("%d\n",h);
   }
   printf("%d\n",k);
}
运行结果:

8
5

变量 h 只在复合语句的语句块内有效,离开该复合语句,该变量则无效。

C语言全局变量

与局部变量相反,在函数之外定义的变量称为全局变量。

由于一个源文件可以包含一个或若干个函数,全局变量可以为本文件中的其他函数所共有,它的有效范围从定义点开始,到源文件结束时结束,全局变量又称为外部变量。例如:

int a=2,b=5;  /*全局变量*/
int f1()      /*定义函数f1()*/
{
   …
}
double c,d;      /*全局变量*/
void f2()     /*定义函数f2()*/
{
   …
}
main()     /*主函数*/
{
   …
}
int e,f;     /*全局变量*/

其中,a、b、c、d、e、f 都是全局变量,但它们的作用范围不同。在 main() 函数、f1() 函数和 f2() 函数中,可以使用 a、b;在 f2() 函数和 main() 函数中可以使用 a、b、c、d。变量 e、f 不能被任何函数使用。

【示例2】编写一个函数,实现同时返回 10 个数的最大值和最小值。
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int min;                /*全局变量min*/
int find( )
{
   int max,x,i;
   x=rand()%101+100; /*产生一个[100, 200]之间的随机数x*/
   printf("  %d",x);
   max=x; min=x;       /* 设定最大数和最小数*/
   for(i=1;i<10;i++)
   {
      x=rand()%101+100; /*再产生一个[100, 200]之间的随机数x*/
      printf("  %d",x);
      if(x>max) 
          max = x;     /* 若新产生的随机数大于最大数,则进行替换*/
      if(x<min)
          min = x;     /* 若新产生的随机数小于最小数,则进行替换*/
    }  
   return max;
}
int main( )
{
    int m=find( );
    printf("\n最大数:%d,最小数:%d\n",m,min);
}
运行结果:

  141  185  172  138  180  169  165  168  196  122
最大数:196,最小数:122

代码中,变量 min 是全局变量,它的作用范围是整个源文件。

程序通过 find() 函数返回最大值,最小值则由全局变量 min 进行传递。由此可见,如果需要传递多个数据,除了使用函数值外,还可以借助全局变量,因为函数的调用只能通过 return 语句带回一个返回值,因此有时可以利用全局变量增加与函数联系的渠道,从函数得到一个以上的返回值。

因此,全局变量的使用增加了函数之间传送数据的途径。在全局变量的作用域内,任何一个函数都可以引用该全局变量。但如果在一个函数中改变了全局变量的值,就会影响其他函数,相当于各个函数间有直接的传递通道。

【示例3】全局变量和局部变量同名的示例。代码如下:
#include <stdio.h>
int a=3,b=5;      /*全局变量a,b*/
int max(int a,int b)  /*局部变量a,b*/
{  
   int c;
   c=a>b?a:b;
   return c;
}
main()
{
   int a=8;      /*局部变量a*/
   printf("%d\n",max(a,b));
}
运行结果:

8

程序中定义了两个全局变量 a 和 b,在 main() 函数中定义了局部变量 a,根据局部变量优先的原则,main() 函数中调用的实参 a 是 8,b 的值是全局变量5,因此程序的运行结果比较的是 8 和 5 的最大值。

在实际使用过程中,建议不在必要时不要使用全局变量,原因如下。

1)占用存储单元

全局变量在程序的全部执行过程中都占用存储单元,而不是仅在需要时才开辟单元。

2)通用性降低

全局变量使得函数的通用性降低了,因为函数在执行时要依赖于其所在的外部变量。如果将一个函数移到另一个文件中,还要将有关的外部变量及其值一起移过去。但若该外部变量与其他文件的变量同名,就会出现问题,会降低程序的可靠性和通用性。

在程序设计中,划分模块时要求模块的“内聚性”强,与其他模块的“耦合性”弱。即模块的功能要单一(不要把许多互不相干的功能放到一个模块中),与其他模块的相互影响要尽量少,而使用全局变量是不符合这个原则的。

一般要求把 C 程序中的函数做成一个封闭体,除了可以通过“实参——形参”的渠道与外界发生联系外,没有其他渠道进行数据传递。这样的程序移植性好,可读性强。

3)降低程序的清晰度

使用全局变量过多,会降低程序的清晰性,人们往往难以清楚地判断出每个瞬时各个全局变量的值。在执行各个函数时,都可能改变全局变量的值,程序容易出错。因此,要限制使用全局变量,而多使用局部变量。

优秀文章