C语言学习笔记之(局部变量和全局变量)
在函数内部定义的变量称为局部变量。前面的实例中绝大多数的变量都是局部变量,其作用域仅仅局限于定义它的函数,无法被其他函数使用。
- 主函数main中定义的变量也是局部变量,只在main函数中有效。main函数也不能使用其他函数中定义的变量。
- 函数的形式参数也属于局部变量,作用范围仅限于函数内部。
- 在复合语句内定义的变量也属于局部变量,只在本复合语句范围内有效。
- 不同函数中,可以使用相同名字的局部变量,它们代表不同对象,互不干扰。
double f(int m,long n)
{
long k; 变量m,n,k的作用域
...
}
int main()
{
int a,b,c;
{
int a; 变量a的作用域,主函数 变量a,b,c的作用域
... 定义的a不起作用
}
}
在函数之外定义的变量称为外部变量,外部变量就是全局变量。全局变量可以为本文件中其他函数所共有。它的有效范围为:从定义变量的位置开始,到本源程序文件结束。例如:
float k;
char f(int x,int y)
{ ...
}
int a=2,b=3;
main()
{ 全局变量a,b的作用域
...
}
例子:分析以下程序的运行结果。
#include <stdio.h>
int d=0;
fun(int p)
{
int d=3;
d+=p;
printf("d=%d,p=%d\n",d,p);
}
int main()
{
int a=2;
fun(a);
d+=a;
printf("d=%d,a=%d\n",d,a);
return 0;
}
上述程序中d为全局变量,在main函数中,起作用的是全局变量d。由于在fun函数中定义了局部变量d,故在fun函数中全局变量d无效,在fun函数中输出为“d=5,p=2”,在main函数中的输出为“d=2,a=2”。
二、变量的存储类别
变量的存储期是该变量在内存中的存在期。某些变量的存在是短暂的,有些变量会被反复地建立和撤销,而另外一些变量存在于程序的整个执行期间。根据变量存在期的不同,可以将变量的存储方式分为静态存储方式和动态存储方式。
静态存储方式是指在程序运行期间分配固定的存储空间,程序执行完毕才释放。动态存储方式是在程序运行期间根据需要动态地分配存储空间,一旦动态过程结束,不论程序结束与否,即释放存储空间。
C程序运行时所用的存储空间一般包括三部分:即程序区、静态存储区和动态存储区。其中,程序区用于存放用户程序,静态存储区用于存放全局变量、静态局部变量,动态存储区用于存放局部变量、函数形参变量、函数返回值等。另外,CPU中的寄存器用于存放寄存器变量。
在C语言中,每个变量和函数都有两个属性:数据类型和数据的存储类别。读者对数据类型已经十分熟悉了,下面着重介绍一下数据的存储类别。
C语言有四种变量存储类别声明符,用来通知编译程序采用哪种方式存储变量,这四种变量存储类别声明符是:auto(自动的)、static(静态的)、register(寄存器的)、extern(外部的)。
1.自动变量auto
自动变量是函数中使用最多的一种局部变量。因为建立和撤消这些变量,都是由系统自动进行的,所以称为自动变量。自动变量用关键字“auto”作存储类别的声明。例如:
auto int a,b=5; /定义自动变量a和b/
实际上,关键字“auto”可以省略,因此,上述定义等价为:
int a,b=5;
2.静态变量static
如果希望在函数调用结束后仍然保留其中定义的局部变量的值,则可以将局部变量定义为静态局部变量。静态局部变量用关键字“static”进行声明,其特点如下:
- 静态局部变量是在静态存储区分配存储单元的。当一个变量被声明为静态时,即在编译时分配存储空间,在整个程序运行期间都不释放。因此,函数调用结束后,它的值并不消失,其值能够保持连续性。
- 静态局部变量是在编译过程中赋初值的,且只赋一次初值,在程序运行时其初值已定,以后每次调用函数时,都不再赋初值,而是保留上一次函数调用结束时的结果。
- 静态局部变量在定义时如果未赋初值,编译系统会把整型变量初始化为0,把实型变量初始化为0.0,把字符型变量初始化为'\0'。
3.例子:阅读以下程序,给出每一次调用过程的分析。
#include<stdio.h>
func(int a,int b)
{
int i=2;
static int m=0;
i+=m+1;
m=i+a+b;
return(m);
}
int main()
{
int k=4,m=1,p;
p=func(k,m);
printf("%d\n",p);
p=func(k,m);
printf("%d\n",p);
return 0;
}
主函数main中定义的k,m,p都为自动局部变量,第1次调用函数func时,将k等于4的值传给a,将m等于1的值传给b。func函数中的局部变量i的初值为2,m的初值为0,在函数调用结束时,i=i+m+1=3,m=i+a+b=8。返回m的值给main函数,故第一次输出为8。
由于func函数中的m被定义为静态局部变量,在函数调用结束后,它并不释放,仍保留m的值为8。在第2次调用func函数时,i的初值为2,而m的初值为8(上次调用结束时的值),在函数调用结束时,i=i+m+1=11,m=i+a+b=16。返回m的值给main函数,故第二次输出为16。
三、将全局变量的作用域扩展到其他文件
一个C程序可以由一个或多个源程序文件组成,在包括多个源程序文件的情况下,如果在一个文件中要引用其他文件中定义的全局变量,则应该在需要引用此变量的文件中,用extern进行说明。
1.例子:别编写两个文件模块,其中文件f1包含主函数,另一个文件f2包含子函数。在f1文件中定义外部变量a,b,c,在f2文件中用extern声明外部变量a,b,c,把变量的作用域扩展到f2文件中。
文件f1.c:
#include<stdio.h>
int a,b,c; /*定义全局变量*/
int main() /*主函数*/
{
void f(); /*函数声明*/
a=3; /*给a和b赋值*/
b=4;
f(); /*调用f函数*/
printf("c=%d\n",c); /*输出c的值*/
}
文件f2.c:
extern int a,b,c; /*把f1文件中已定义的全局变量的作用域扩展到本文件*/
void f() /*定义函数实现c=a+b*/
{
c=a+b;
}
-
编译和运行包括多个文件的程序时,可用Visual C++ 6.0同时打开多个文件,然后分别编译每个文件,继而连接和运行即可。例如,上题中可同时打开f1.c和f2.c文件,然后分别编译f1.c和f2.c两个文件,这时编译器会自动建立工作区和项目文件,继而连接运行即可得到结果。
-
extern只能用来声明变量,不能用来定义变量,因为它不产生新的变量,只是声明该变量已在其他地方定义过。
-
extern不能用来初始化变量。例如:“extern int x=1;”是错误的。
四、将外部变量的作用域限制在本文件中
在设计程序时,如果希望在一个文件中定义的全局变量仅限于被本文件引用,而不能被其他文件引用,则可以在定义此全局变量时加一个static声明,例如:
static int x;
此时,全局变量的作用域仅限于本文件,在其他文件中即使进行了extern声明,也无法使用该变量。这种加上static声明的全局变量称为静态全局变量。
| 变量存储类型 | 函数内 | 函数外 | ||
|---|---|---|---|---|
| 作用域 | 存在性 | 作用域 | 存在性 | |
| 自动变量 | 是 | 是 | 否 | 否 |
| 寄存器变量 | 是 | 是 | 否 | 否 |
| 静态局部变量 | 是 | 是 | 否 | 是 |
| 静态全局变量 | 是 | 是 | 是(只限本文件) | 是 |
| 外部变量 | 是 | 是 | 是 | 是 |
由表可以看出,自动变量和寄存器变量在函数内外的作用域和存在性都是一致的,即离开函数后,值就不能被引用了,也不存在了。静态局部变量的作用域和存在性不一致,离开函数后,变量值存在,但不能被引用。静态全局变量和外部变量的作用域和存在性也是一致的,在离开函数后变量值仍存在,且可被引用,不过静态全局变量只限本文件内引用。
C语言学习笔记之(局部变量和全局变量)
https://www.wsjj.top/archives/c13
评论