变量的作用域与生存期
§ 作用域与生存期概述
变量的作用域(空间特性)
变量的作用域也称为可见性,指变量能够被访问的范围
分为局部变量和全局变量两类:局部变量的范围较窄,限定在程序中的部分区域;全局变量的范围较宽,可以是整个文件甚至是整个程序
变量的存储类别(时间特性)
除作用域(可见性)外的另外两个特性:变量存放在计算机何处,变量何时存在 — 存储类别
变量存在的位置,RAM 或 CPU寄存器
RAM 划分:代码区、静态存储区、动态存储区
存储类别,RAM,static,auto,CPU,register
代码区静态存储区动态存储区全局变量、局部静态变量形参变量局部动态变量( auto register)
函数调用现场保护和返回地址等
§内部变量
局部变量 ---内部变量
定义:在 函数内或复合语句内定义,只在本函数内或复合语句内有效
说明:
main中定义的变量只在 main中有效
不同函数中同名变量,占不同内存单元
形参属于局部变量
可定义在复合语句中有效的变量
局部 (空间特性 )变量可用存储类型 (时间特性 ),auto
register static ( 默认为 auto,可省略)
float f1(int a)
{ int b,c;
…….
}
char f2(int x,int y)
{ int i,j;
……
}
main()
{ int m,n;
…….
}
a,b,c有效
x,y,i,j有效
m,n有效
void sub()
{
int a,b;
a = 6;
b = 7;
printf("sub:a=%d,b=%d\n",a,b);
}
void main()
{ int a,b;
a = 3;
b = 4;
printf("main:a=%d,b=%d\n",a,b);
sub();
printf("main:a=%d,b=%d\n",a,b);
}
#define N 5
void main()
{ int i;
int a[N] = {1,2,3,4,5};
for(i=0;i<N/2;i++)
{ int temp;
temp = a[i];
a[i] = a[N-i-1];
a[N-i-1] = temp;
}
for(i = 0;i < N;i++)
printf("%d ",a[i]);
}
例 不同函数中同名变量 例 复合语句中变量运行结果,5 4 3 2 1
运行结果:
main:a=3,b=4
sub:a=6,b=7
main:a=3,b=4
自动变量 ( auto )
格式,[auto] 类型 变量名列表; auto 可省略
auto int a; 等价于 int a;
自动变量的生存期:自动变量存在于 RAM 中的动态存储区 —“栈”,并且仅当定义它的函数或复合语句被执行时,才创建该变量,执行结束后该变量自动被删除掉,释放占用的内存空间。
自动变量用的最多,不会永久占用内存空间。
#include <stdio.h>
main()
{ auto int a,b,c;
a=1,b=2;
c = add(a,b);/*创建 add形参和局部变量 */
{
float x = c;
printf("x=%f",x);
}
printf("c=%d",c);
}
int add(int x,int y)
{ int z;
z=x+y;
return (z);
}
a,b,c有效
x,y,z有效
x有效
寄存器变量
格式,register 类型 变量名列表;
for(register int a=0; a<1000000; a++)
寄存器变量存在于 cpu 内部的寄存器中,数量很少,一般是将循环使用很多次的变量放在寄存器中,加快执行速度。
注意:
只有整型变量能放在寄存器中,包括,int,char、
short,long等。
寄存器变量必须是 auto 类型的局部变量、形参,不能是全局变量或静态变量。
由于寄存器数量很少,不能保证定义的寄存器变量总是能分配到寄存器,这时作为普通变量。
对于寄存器变量,不能做取地址 ( & )运算。
例 使用寄存器变量
int fac(int n)
{
register int i,f = 1;
for(i = 1;i <= n;i++)
f = f*i;
return(f);
}
void main()
{
int i;
for(i = 1;i <= 1000;i++)
printf(“%d!=%d \n”,i,fac(i));
}
1、只有 局部自动变量和形式参数 可以作为寄存器变量
2、不能定义 任意 多个寄存器变量
3、局部 静态 变量不能定义为寄存器变量
静态内部变量
格式,static 类型 变量名列表;
static int a;
形参不能是定义成 static。
内部变量定义成 static 后,作用域不变,但生存期变长,在整个程序执行前就存在,直到程序结束才清除掉,其生存期为整个程序的运行期。
使用注意:
静态变量只初始化一次。
静态变量的值具有“记忆”性。
尽管生存期变长,但作用域 (可见性 )仍然局限在定义它的局部范围内。
void main()
{
int i;
for(i=0;i < 3;i++)
inc1();
for(i=0;i < 3;i++)
inc2();
}
例 静态内部变量的生存期
#include <stdio.h>
void inc1()
{
int x=0;
x++;
printf("in inc1 x=%d\n",x);
}
void inc2()
{
static int x=0;
x++;
printf("in inc2 x=%d\n",x);
}
运行结果:
in inc1 x=1
in inc1 x=1
in inc1 x=1
in inc2 x=1
in inc2 x=2
in inc2 x=3
§外部变量 ---全局变量
定义:在 函数外定义,可为 本文件所有函数共用
作用域:从 定义变量的位置开始 到本源文件结束,
及有 extern说明 的其它源文件
生存期:整个程序运行期间
!!! 应尽量少使用全局变量,因为:
全局变量在程序全部执行过程中占用存储单元
降低了函数的通用性、可靠性,可移植性
降低程序清晰性,容易出错定义 说明
次数,只能 1次 可说明多次
位置,所有函数之外 函数内或函数外
分配内存,分配内存,可初始化 不分配内存,不可初始化
用 extern 声明 外部变量,extern 数据类型 变量表;
外部变量 定义 与外部变量 说明 (声明 )不同
若外部变量与局部变量 同名,则外部变量 被屏蔽
外部变量可用存储类型,缺省 或 static
/*ch7_17.c*/
int a = 3,b = 5;
int max(int a,int b)
{ int c;
c=a>b?a:b;
return(c);
}
void main()
{
int a = 8;
printf("max=%d",max(a,b));
}
例 外部变量与局部变量(同名的局部变量 屏蔽 外部变量)
运行结果,max=8
float max,min;
float average(float array[],int n)
{ int i; float sum = array[0];
max = min = array[0];
for (i=1; i<n; i++)
{ if( array[i] > max ) max = array[i];
else if( array[i] < min) min = array[i];
sum += array[i];
}
return (sum/n);
}
void main()
{ int i; float ave,score[10];
/*Input data to score 省略 */
ave = average(score,10);
printf("max=%6.2f\nmin=%6.2f\n
average=%6.2f\n",max,min,ave);
}
作用域
max
min
外部变量增加了函数间数据联系的渠道
int p=1,q=5;
float f1(int a)
{ int b,c;
…….
}
int f3()
{…..
}
char c1,c2;
char f2(int x,int y)
{ int i,j;
……
}
main()
{ int m,n;
…….
}
c1,c2原来 的作用范围
p,q的作用范围
extern char c1,c2;
extern char c1,c2;
c1,c2
的作用范围扩展后
c1,c2
的作用范围扩展后用 extern 声明外部变量可以扩展外部变量的作用域
int add(int x,int y)
{
int z;
z=x+y;
return z;
}
void main()
{
extern int a,b;
printf(“a+b=%d \n",add(a,b));
}
int a=3,b=4;
例 用 extern扩展外部变量作用域运行结果:
a+b=7
例 用 extern将变量的作用域扩展到其它文件中
int x=10,y=10;
extern void sub();
void add(void)
{ int y =5;
y = 10+x;
x *= 2;
printf("add:y=%d:",y);
}
void main()
{ x+=5;
add();
sub();
printf("main:x=%d,main:y=
%d\n",x,y);
}
extern int x;
void sub()
{
int y=5;
x -= y;
printf("sub:y=%d;",y);
}
file1.c
file2.c
运行结果:
add:y=25;sub:y=5;
main:x=25;main:y=10;
static int x=10;
void add2()
{
extern int y;
x+=10;
y+=2;
printf("in add2 x=%d\n",x);
}
例 static 型外部变量的作用域受到限制,限制在本文件内使用运行结果:
in add1 x=4
in add2 x=20
in add1 x=6
in add2 x=30
x=6;y=13
static int x=2;
int y=3;
extern void add2();
void add1();
void main(){
add1();add2();add1();add2();
printf("x=%d;y=%d\n",x,y);
}
void add1()
{
x+=2;
y+=3;
printf("in adda x=%d\n",x);
}
int i;
void main()
{
void prt();
for(i = 0;i < 5;i++)
prt();
}
void prt()
{
for(i = 0;i < 5;i++)
printf(“%c”,’*’);
printf(“\n”);
}
例 外部变量副作用运行结果,*****
例 文件 file1.c
int a;
void main( )
{ …….
…….
f2;
…….
f1;
…….
}
f1( )
{ auto int b;
………
f2;
……..
}
f2( )
{ static int c;
………
}
C作用域
b作用域
a作用域
main f2 f1main f1f2 main
a生存期,
b生存期,
c生存期,
变量存储类型静态动态存储方式程序整个运行期间函数调用开始至结束生存期编译时赋初值,只赋一次每次函数调用时赋初值自动赋初值 0或空字符不确定未赋初值静态存储区动态区存储区 寄存器局部变量 外部变量作用域 定义变量的函数或复合语句内 本文件 其它文件
局部变量默认为 auto型
register型变量个数受限,且不能为 long,double,float型
局部 static变量具有 全局寿命 和 局部可见性
局部 static变量具有 可继承性
extern不是变量定义,可扩展外部 变量作用域
register 局部 staticauto 外部 static 外部存储类别