您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 项目/工程管理 > 第7章 变量的作用域与生存期
第七章变量的作用域与生存期§7.1作用域与生存期概述▲变量的作用域(空间特性)●变量的作用域也称为可见性,指变量能够被访问的范围。●根据不同的作用域,变量可分为局部变量和全局变量两类。局部变量的作用范围限定在程序中的部分区域(函数、复合语句);全局变量的作用范围可以是整个文件甚至是整个程序。▲变量的存储类别(时间特性)除作用域(可见性)外的另外两个特性:变量所在存储单元如何分配(存储位置)?变量何时存在(生存期)?———存储类别。●变量的存放位置:RAM或CPU寄存器●内存区域划分:代码区、静态存储区、动态存储区●存储类别:静态存储、自动存储●静态存储方式:存放在静态存储区,编译时就分配确定的相对位置,程序调入内存时即分配了固定的内存单元(静态分配)生存期为整个程序的运行过程。●自动存储方式:存放在动态存储区(栈区),临时分配。生存期仅在函数或复合语句(调用)执行期间。▲定义变量的声明格式决定了存储类别,进而决定了变量的生存期;而该定义变量的声明位置(内部/外部)则决定了变量的作用域.▲内部变量※定义:在函数内或复合语句内定义,只在本函数内或复合语句内有效。※说明:●main中定义的变量只在main中有效;●不同函数中同名变量,占不同内存单元;●形参属于内部变量;●分为自动变量、寄存器变量和静态内部变量。§7.2内部变量floatf1(inta){intb,c;…….}charf2(intx,inty){inti,j;……}main(){intm,n;…….}a,b,c有效x,y,i,j有效m,n有效voidsub(){inta,b;a=6;b=7;printf(sub:a=%d,b=%d\n,a,b);}voidmain(){inta,b;a=3;b=4;printf(main:a=%d,b=%d\n,a,b);sub();printf(main:a=%d,b=%d\n,a,b);}#defineN5voidmain(){inti;inta[N]={1,2,3,4,5};for(i=0;iN/2;i++){inttemp;temp=a[i];a[i]=a[N-i-1];a[N-i-1]=temp;}for(i=0;iN;i++)printf(%d,a[i]);}【例】不同函数中同名变量【例】复合语句中变量运行结果:54321运行结果:main:a=3,b=4sub:a=6,b=7main:a=3,b=4▲自动变量(auto)※格式:[auto]类型变量名列表;auto可省略,autointa;等价于inta;※自动变量的生存期:自动变量存在于RAM中的动态存储区—“栈”,并且仅当定义它的函数或复合语句被执行时,才创建该变量,执行结束后该变量自动被删除掉,释放占用的内存空间。※自动变量用的最多,不会永久占用内存空间。#includestdio.hmain(){autointa,b,c;a=1,b=2;c=add(a,b);/*创建add形参和局部变量*/{floatx=c;printf(x=%f,x);}printf(c=%d,c);}intadd(intx,inty){intz;z=x+y;return(z);}a,b,c有效x,y,z有效x有效▲寄存器变量(建议不使用)※格式:register类型变量名列表;※关键字register的真正作用是提醒编译程序所定义的变量在程序中使用频率较高。※注意:●只有字符型、整型变量能放在寄存器中,包括:int、char、short、long等。●寄存器变量必须是auto类型的局部变量、形参,不能是全局变量或静态变量。※由于寄存器数量很少,不能保证定义的寄存器变量总是能分配到寄存器,这时作为普通变量。※对于寄存器变量,不能做取地址(&)运算。【例】使用寄存器变量intfac(intn){registerinti,f=1;for(i=1;i=n;i++)f=f*i;return(f);}voidmain(){inti;for(i=1;i=1000;i++)printf(“%d!=%d\n”,i,fac(i));}▲静态内部变量※静态存储方式存放,作用域仍然是仅限于所在的函数或复合语句。※格式:static类型变量名列表;staticinta;※形参不能是定义成static。※使用注意:●静态变量只初始化一次。●静态变量的值具有“记忆”性。●尽管生存期变长,但作用域(可见性)仍然局限在定义它的局部范围内。voidmain(){inti;for(i=0;i3;i++)inc1();for(i=0;i3;i++)inc2();}【例】静态内部变量的生存期#includestdio.hvoidinc1(){intx=0;x++;printf(ininc1x=%d\n,x);}voidinc2(){staticintx=0;x++;printf(ininc2x=%d\n,x);}运行结果:ininc1x=1ininc1x=1ininc1x=1ininc2x=1ininc2x=2ininc2x=3§7.3外部变量●定义:在函数外定义●作用域:(1)默认:从定义变量的位置开始到本源文件结束。(2)扩展:到其它源文件(其它源文件须用关键字extern声明变量)。(3)限制在本源文件:定义时加关键字static。●生存期:整个程序运行期间定义声明次数:只能1次可说明多次位置:所有函数之外函数内或函数外分配内存:分配内存,可初始化不分配内存,不可初始化●若外部变量与内部变量同名,则在函数中外部变量被屏蔽。/*ch7_17.c*/inta=3,b=5;intmax(inta,intb){intc;c=ab?a:b;return(c);}voidmain(){inta=8;printf(max=%d,max(a,b));}【例】外部变量与内部变量(同名的局部变量屏蔽外部变量)运行结果:max=8floatmax,min;floataverage(floatarray[],intn){inti;floatsum=array[0];max=min=array[0];for(i=1;in;i++){if(array[i]max)max=array[i];elseif(array[i]min)min=array[i];sum+=array[i];}return(sum/n);}voidmain(){inti;floatave,score[10];/*Inputdatatoscore省略*/ave=average(score,10);printf(max=%6.2f\nmin=%6.2f\naverage=%6.2f\n,max,min,ave);}作用域maxmin外部变量增加了函数间数据联系的渠道intp=1,q=5;floatf1(inta){intb,c;…….}intf3(){…..}charc1,c2;charf2(intx,inty){inti,j;……}main(){intm,n;…….}c1,c2原来的作用范围p,q的作用范围externcharc1,c2;externcharc1,c2;c1,c2的作用范围扩展后c1,c2的作用范围扩展后用extern声明外部变量可以扩展外部变量的作用域intadd(intx,inty){intz;z=x+y;returnz;}voidmain(){externinta,b;printf(“a+b=%d\n,add(a,b));}inta=3,b=4;【例】用extern扩展外部变量作用域运行结果:a+b=7【例】用extern将变量的作用域扩展到其它文件中intx=10,y=10;externvoidsub();voidadd(void){inty=5;y=10+x;x*=2;printf(add:y=%d:,y);}voidmain(){x+=5;add();sub();printf(main:x=%d,main:y=%d\n,x,y);}externintx;voidsub(){inty=5;x-=y;printf(sub:y=%d;,y);}file1.cfile2.c运行结果:add:y=25;sub:y=5;main:x=25;main:y=10;staticintx=10;voidadd2(){externinty;x+=10;y+=2;printf(inadd2x=%d\n,x);}【例】static型外部变量的作用域受到限制,限制在本文件内使用。运行结果:inadd1x=4inadd2x=20inadd1x=6inadd2x=30x=6;y=13staticintx=2;inty=3;externvoidadd2();voidadd1();voidmain(){add1();add2();add1();add2();printf(x=%d;y=%d\n,x,y);}voidadd1(){x+=2;y+=3;printf(inaddax=%d\n,x);}iti;voidmain(){voidprt();for(i=0;i5;i++)prt();}voidprt(){for(i=0;i5;i++)printf(“%c”,’*’);printf(“\n”);}【例】外部变量副作用运行结果:*****【例】文件file1.cinta;voidmain(){…….…….f2;…….f1;…….}f1(){autointb;………f2;……..}f2(){staticintc;………}C作用域b作用域a作用域mainf2f1mainf1f2maina生存期:b生存期:c生存期:▲数据在内存中的分配方式※静态内存分配的特点●由编译器在编译阶段自动完成,不需要程序设计者干预或管理;●分配效率高;●由于分配的存储区域其大小是固定不可变的,也存在明显的不足之处;※动态内存分配(1)栈分配:自动变量存放在动态存储区中的栈区,只有当其所在的函数或复合语句被调用执行时才在栈区中为其临时分配存储单元,函数或复合语句一次执行结束后,所占用的存储单元就被释放,且后分配的存储单元会被先释放。§7.4动态内存分配▲数据在内存中的分配方式※动态内存分配(2)堆分配堆(heap)是动态内存区域中一部分自由空闲区域(一般是不连续,使用链表方式来管理,可包括多个大小不等的空闲区域)。C程序设计者可以通过库函数在堆中申请存储空间,不需要时可以释放(即返回给堆),释放后的存储空间又可以被再次申请使用。优点:根据实际需要的大小来申请和分配存储空间,不需要时随时可以释放。注意,申请的存储空间不宜过大。▲通过库函数申请和释放存储空间的方法(1)申请malloc函数void*malloc(unsignedintsize);分配size个字节的连续存储空间。calloc函数void*calloc(unsignednum,unsignedsize);分配一块连续的容量为(num*size)个字节的存储空间。注意:两个函数的返回值。(2)释放:voidfree(void*prt);释放由prt所指向的内存空间,该内存空间此前由函数malloc()或calloc()和realloc()分配而来。▲应用举例:例7-7,例7-8./*源文件7-7.c*/#includemath.h#includestdlib.hvoidmain(){...a=(int*)calloc(n,sizeof(int));/*申请分配n*sizeof(int)字节*/if(a==NULL)/*如果分配失败,退出程序*/{printf(“outofmemory!\n”);exit(1);}/*初始化内存空间,并按照筛选法求出素数*/for(i=1;in;i++)a[i]=i+1;/*使用分配的存储空间(数组a占用)*/...free(a);/*不再需要申请的存储单元,释放*/}
本文标题:第7章 变量的作用域与生存期
链接地址:https://www.777doc.com/doc-3340193 .html