欢迎来到三一办公! | 帮助中心 三一办公31ppt.com(应用文档模板下载平台)
三一办公
全部分类
  • 办公文档>
  • PPT模板>
  • 建筑/施工/环境>
  • 毕业设计>
  • 工程图纸>
  • 教育教学>
  • 素材源码>
  • 生活休闲>
  • 临时分类>
  • ImageVerifierCode 换一换
    首页 三一办公 > 资源分类 > PPT文档下载  

    《c语言程序设计基础》5函数.ppt

    • 资源ID:5896098       资源大小:559.50KB        全文页数:101页
    • 资源格式: PPT        下载积分:15金币
    快捷下载 游客一键下载
    会员登录下载
    三方登录下载: 微信开放平台登录 QQ登录  
    下载资源需要15金币
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    《c语言程序设计基础》5函数.ppt

    第5章 函数,第5章 函数,本章内容,5.2 函数原型与函数调用,5.3 函数的嵌套调用,5.4 函数的递归调用,5.1 函数基础知识,第5章 函数,本章内容,5.6 变量的作用域,5.7 变量的存储类别,5.5 调用与被调用函数间的数据传递,5.1 函数基础知识,本节内容,5.1.2 函数的分类,5.1.3 函数的定义,5.1.1 函数的概念,5.1 函数基础知识,由图可以看出一个C语言程序可以包含若干个源文件,而每个源文件又是由若干个函数构成的,因此,也可以说函数是语言源程序的基本模块,程序的功能是通过对函数模块的调用来实现的。,5.1.1 函数的概念,函数,就是一个能够完成一定功能的执行代码段。C语言程序的所有功能都是通过函数之间的调用来实现的。使用函数有以下优点:程序结构清晰,可读性好。减少重复编码的工作量。可多人共同编制一个大程序,缩短程序设计周期,提高程序设计和调试的效率。可以将一些重复使用的功能或操作定义成一个函数,在其他函数中如果需要可以直接调用这个函数,而省掉了很多重复性的工作。并且使程序结构看起来更加简单清晰。,5.1.1 函数的概念,#include/包含预处理命令main()/主函数int max1(int x,int y);/max1函数声明int a,b,c;/声明部分,定义变量printf(Please input two integers:n);/调用printf函数 scanf(%d,%d,5.1.1 函数的概念,在语言中,所有的函数定义,包括主函数main在内,都是平行的。也就是说,在一个函数的函数体内不能再定义另一个函数,即不能嵌套定义。但是函数之间允许相互调用,也允许嵌套调用。习惯上把调用者称为主调函数。函数还可以自己调用自己,称为递归调用。main 函数是主函数,它可以调用其它函数,而不允许被其它函数调用。因此,语言程序的执行总是从main函数开始,完成对其它函数的调用后再返回到main函数,最后由main函数结束整个程序。一个语言源程序必须有且只有一个主函数main。,5.1.2 函数的分类,从函数定义的角度分类库函数。库函数由系统提供,用户无须定义,也不必在程序中作类型说明,只需在程序前包含该函数原型的头文件,即可在程序中直接调用。在本书第二章对库函数作了详细说明,在C程序中大量应用了库函数。例如,printf、scanf、getchar、putchar、gets、puts、strcat等函数。用户自定义函数。用户自定义函数是用户根据需要编写的函数。用户自定义函数不仅要在程序中定义函数本身,而且在主调函数模块中还必须对该被调函数进行类型说明,然后才能使用。,5.1.2 函数的分类,根据函数调用是否有返回值分类有返回值函数。此类函数被调用执行完后将向调用者返回一个执行结果,称为函数返回值。如数学函数即属于此类函数。由用户定义的这种要返回函数值的函数,必须在函数定义和函数说明中明确返回值的类型,如例5-1中的max1函数,执行完后将向它的调用者(main函数)返回z的值,并赋给变量c。无返回值函数。此类函数用于完成某项特定的处理任务,执行完成后不向调用者返回函数值。这类函数类似于其它语言的过程。由于函数无须返回值,用户在定义此类函数时可指定它的返回值为“空类型”,空类型的说明符为“void”。,5.1.2 函数的分类,#include/包含预处理命令main()/主函数void max2(int x,int y);/max2函数声明int a,b;/声明部分,定义变量printf(Please input two integers:n);/调用printf函数 scanf(%d,%d,5.1.2 函数的分类,从主调函数和被调函数之间数据传送的角度分类无参函数。函数定义、函数说明及函数调用中均不带参数。主调函数和被调函数之间不进行参数传送。此类函数通常用来完成一组指定的功能,可以返回或不返回函数值。如例5-2中helloworld函数,函数名后的小括号内没有参数,即为无参函数。有参函数。也称为带参函数。在函数定义及函数说明时用到的参数,称为形式参数(简称为形参)。在函数调用时也必须给出参数,称为实际参数(简称为实参)。进行函数调用时,主调函数将把实参的值传送给形参,供被调函数使用。如例5-1中的max1或max2函数都有两个整型的参数x和y。,5.1.3 函数的定义,5.1.3.1 函数定义的形式函数定义也就是确定该函数应完成什么功能以及如何实现这一功能。函数分为无参函数和有参函数。无参函数定义的一般格式如下所示:类型标识符 函数名()声明部分 语句部分,5.1.3 函数的定义,说明:类型标识符和函数名合称为函数头,其中类型标识符用于确定函数类型即该函数的返回值类型,例如整型、实型、字符型等。省略类型标识符时默认为int类型。函数名唯一标识函数的名称,通过函数名可实现函数的调用。C语言中函数名必须是合法的标识符,即满足标识符的命名规则。在很多情况下都不要求无参函数有返回值,此时函数类型符可以写为void。由左、右大括号括起来的部分称为函数体。其中声明部分对函数内部用到的变量以及变量的类型进行说明,并说明该函数中所调用的函数类型。语句部分,规定函数中要执行的语句,由C语言的基本语句组成,是函数的核心部分。,5.1.3 函数的定义,有参函数定义的一般格式如下所示:类型标识符 函数名(形式参数类型说明 形式参数表列)声明部分 语句部分函数名后括号中的内容是对形式参数的说明,明确指出该函数所带形式参数的个数及各参数的类型。形式参数表列可以为空,即定义的函数为无参函数,也可以有多个形参,当有多个形参时,各参数之间用逗号隔开。但无论有没有形参,函数名后的括号都不能丢掉。,5.1.3 函数的定义,#include int dif(int x,int y)int z;z=x y?x-y:y-x;return(z);main()/主函数int a,b,c;/声明部分,定义变量printf(Please input two integers:n);/调用printf函数 scanf(%d,%d,/调用printf函数,5.1.3 函数的定义,5.1.3.2 空函数这种函数什么也不做,只是用来占用一个位置,在程序需要扩充功能的时候,用一个编好的函数取代它。这类函数称为空函数,其定义形式为:类型标识符 函数名()函数体没有任何语句,调用此函数也不能完成任何实际操作,空函数的功能是使程序结构清晰,需要时可以用其它函数代替。,5.2 函数原型与函数调用,本节内容,5.2.2 函数的参数,5.2.3 函数的调用,5.2.4 函数的返回值,5.2.1 函数的原型,5.2.1 函数的原型,编译程序在处理函数调用时,首先要获得执行被调函数的接口信息,确认函数调用语句的正确性,然后进入被调函数执行。因此对被调函数有以下要求:被调函数必须是已经存在的用户自定义函数或者库函数。如果调用的是库函数,在程序的开头必须用#include 或#include“*.h”将库函数所在头文件包含进来。头文件以字母h为后缀,其中包含了库函数的原型说明。如果使用的是自定义函数,在主调函数中应对被调函数作原型说明。通常函数原型说明放在主调函数的开始位置或整个程序的开始。,5.2.1 函数的原型,在语言程序中有两种方式可以说明函数原型。函数类型 函数名(数据类型1,数据类型2,);函数类型 函数名(数据类型1 形式参数1,数据类型2 形式参数2,);函数类型是该函数返回值的数据类型。如果是无值型则表示函数没有返回值。函数名为C语言的合法标识符。括号中的内容为该函数的形式参数说明。可以只有数据类型而没有形式参数,也可以两者都有。,#include main()void calc(float x,float y,char opr);/对被调函数calc的说明 float a,b;char opr;printf(Input expression:);scanf(%f%c%f,5.2.1 函数的原型,实际在C语言中,如果有以下几种情况时可以在主调函数中省去对被调函数的说明:当被调函数的函数定义出现在主调函数之前时。如果已在所有函数定义之前,在函数外预先说明了各个函数的类型。对库函数的调用不需要再作说明,但必须把该函数的头文件用include命令包含在源文件前面。在Turbo C环境下,如果被调函数的返回值是整型或字符型时,可以不对被调函数作说明。在VC环境下,即便被调函数的返回值是整型或字符型,当被调函数的函数定义出现在主调函数之后时,一定要先声明函数,再使用。,5.2.2 函数的参数,函数的参数可分为形参和实参两种。在定义函数时函数名后括号内的变量表列称为形式参数表列,简称为形参。只有在函数被调用时,该函数的形参才在内存中开辟空间,一旦调用结束,所占用的存储空间也就随之释放。因此,形参变量只在整个函数体内都可以使用。调用函数时函数名后括号内的变量表列称为实在参数表列,简称为实参。实参的值是在主调函数中给定的,在调用过程中将实参的值传递给相应的形参,从而实现主调函数向被调函数的数据传送。实参出现在主调函数中,进入被调函数后,实参变量也不能使用。,5.2.2 函数的参数,形参和实参具有以下特点:形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只有在函数内部有效。函数调用结束返回主调函数后则不能再使用该形 参变量。实参可以是常量、变量、表达式、函数等,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参,而形参只能是变量。实参和形参在数量上,顺序上应严格一致,在类型上应相同或赋值兼容,否则会发生“类型不匹配”的错误。注意:字符型与整型可以兼容。,5.2.2 函数的参数,函数调用过程中发生的数据传送是单向值传递。即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参,实参到形参的传递是单向的。C语言的参数传递机制有两种:值传递和地址传递。值传递的特点是:先对实参求值,然后将其值传送给相应的形参,形参的作用范围仅在该函数内,即函数的形式参数作为函数的局部变量处理,不会影响实参变量的值,实参向形参的传递是单向的。地址传递的特点是:实参是地址量(如数组名指针),实参传递地址给形参,这样形参和实参存在于一个地址空间,被调函数对形参做的任何操作都会影响主调函数中的实参变量,实参与形参的传递是双向的。,5.2.2 函数的参数,#include void swap(int x,int y)int z;z=x;x=y;y=z;printf(x=%d,y=%d,x,y);main()int a,b;printf(please input a,b:);scanf(%d,%d,5.2.3 函数的调用,5.2.3.1 函数调用格式若被调函数是有参函数,则直接使用函数名和实参的方法,其一般格式为:函数名(实参表列)函数调用的过程中,将主调函数中的实参值赋给被调函数中对应的形式参数,然后进入被调函数执行,若被调函数是有返回值函数,则执行结束后可将结果返回给主调函数。如若调用无参函数,其一般格式为:函数名(),5.2.3 函数的调用,#include int dif(int x,int y)int z;z=x y?x-y:y-x;return(z);main()int m,n,diff;m=10;n=4;diff=dif(m,n);printf(dif=%d n,diff);,5.2.3 函数的调用,上述函数是有参函数,在调用时需注意以下几点:实参个数和形参个数应该相同,在传递过程中按顺序对应。实参的类型必须和形参类型一一对应。如果不同,将实参类型转换成形参类型然后传递。实参可以是常量、变量或者表达式,而形参只能是变量。实参可以和形参同名。如果有多个实参,实参间用逗号隔开,并需注意实参的求值顺序。,5.2.3 函数的调用,5.2.3.2 函数调用作为语句的函数调用。其一般格式为:函数名(实在参数表);这种方法经常用于调用一个可以忽略返回值或没有返回值的函数。作为表达式的函数调用。凡是表达式可以出现的地方都可以出现函数调用。其一般格式为:变量名=函数表达式这种方式通常用于调用带返回值的函数。作为参数的函数调用。函数作为另一个函数调用的实际参数出现。这种情况是把该函数的返回值作为实参进行传递,因此要求该函数必须是有返回值的。,5.2.3 函数的调用,#include int cube(int x)/定义cube函数 return(x*x*x);main()int a;printf(nEnter an integer number:);scanf(%d,5.2.4 函数的返回值,函数的返回值是指函数调用结束后,由被调函数返回给主调函数的值。被调函数运算的结果通过return语句返回主调函数。return 语句的一般形式为:return 表达式;或者为:return(表达式);该语句的功能:终止被调函数的运行,返回主调函数;,5.2.4 函数的返回值,若有返回值,将返回值带回主调函数。其中“表达式”可以是常量变量函数调用等。一个函数中允许有多个return语句,即函数可以有多个出口。但每次调用只能有一个return 语句被执行,因此最多只能返回一个函数值。函数返回值的类型应和定义函数时的函数类型保持一致。如果两者不同,则以函数类型为准,自动对返回值进行类型转换。即函数类型决定函数返回值的类型。,5.2.4 函数的返回值,#include main()int dif(float x,float y);float a,b;int c;printf(please input a,b:);scanf(%f,%f,5.2.4 函数的返回值,程序中dif函数还可以定义成下面的形式:int dif(float x,float y)float z;if(xy)return(z=x-y);else return(z=y-x);如果函数值为整型,在函数定义时可以省去类型说明。如果函数没有返回值,应明确定义为“空类型”,类型说明符为“void”。为了使程序有良好的可读性并减少出错,凡不要求返回值的函数都应定义为空类型。,5.3 函数的嵌套调用,语言规定,函数中不允许嵌套定义函数,但是语言允许在一个函数的调用过程中调用另一个函数,即一个被调函数中再调用其他函数,这称为函数的嵌套调用。,main函数 调用函数 A;,5.3 函数的嵌套调用,嵌套的执行过程,函数 B,函数 A 调用函数 B;,#include int dif(int x,int y,int z);/dif函数的说明int max(int x,int y,int z);/max函数的说明int min(int x,int y,int z);/min函数的说明void main()int a,b,c,d;printf(please input a b c:);scanf(%d%d%d,/调用max和min函数,5.3 函数的嵌套调用,int max(int x,int y,int z)/定义max函数,求三个数中最大值 int r;r=xy?x:y;return(rz?r:z);int min(int x,int y,int z)/定义min函数,求三个数中最小值 int r;r=xy?x:y;return(rz?r:z);,5.4 函数的递归调用,一个函数在它的函数体内直接或间接地调用它自身称为函数的递归调用,这种函数称为递归函数。递归算法必须满足三个条件:有明确的结束递归的条件。可以将要解决的问题转换为一个或多个相对简单的新问题,且新问题的解法和原问题解法相同,它们之前的区别通常只有规模不同。递归的次数应有限,即随着程序的执行最终可以达到结束递归的条件。,5.4 函数的递归调用,函数直接或间接的调用自身叫函数的递归调用,int f(int x)int y,z;z=f(y);.return(2*z);,直接递归,间接递归,5.4 函数的递归调用,求n!以求4的阶乘为例:4!=4*3!,3!=3*2!,2!=2*1!,1!=1,0!=1递归公式:n!=1 当n=1时 n!=n*(n-1)!当n 1时 递归结束条件:当n=1或n=0时,n!=1,5.4 函数的递归调用,#include void dtoo(int x)/定义递归函数dtoo unsigned int m;m=x%8;/除8取余数x=x/8;/除8求商if(x!=0)dtoo(x);printf(%d,m);main()unsigned int n;printf(please decimal digit n:);scanf(%d,5.4 函数的递归调用,#include float fac(int n)float f=0;if(n0)printf(n0,error!);else if(n=0|n=1)f=1;else f=fac(n-1)*n;return(f);main()int n;float y;printf(Input a integer n:);scanf(%d,5.4 函数的递归调用,汉诺塔:有A,B,C三个塔座,A上套有n个直径不同的圆盘,按直径从小到大叠放,形如宝塔,编号1,2,3n。要求将n个圆盘从A移到C,叠放顺序不变,移动中遵循下列原则:每次只能移一个圆盘圆盘可在三个塔座上任意移动任何时刻,每个塔座上不能将大盘压到小盘上,5.4 函数的递归调用,分析3个盘子的情况:1.将A座上2个盘子移到B座(借助C)2.将A座上1个盘子移到C座3.将B座上2个盘子移到C座(借助A)其中第2 步可以直接实现第1、3步还需要递归分解,5.4 函数的递归调用,递归分解:第1 步将A座上2个盘子移到B座(借助C),分解为:1.1 将A上一个盘子从A移到C;1.2 将A上一个盘子从A移到B;1.3 将C上一个盘子从C移到B。,5.4 函数的递归调用,递归分解:第3步将B座上2个盘子移到C座(借助A),分解为:3.1 将B上一个盘子从B移到A3.2 将B上一个盘子从B移到C3.3 将A上一个盘子从A移到C,5.4 函数的递归调用,将以上综合起来,可得到移动3个盘子的步骤为:AC,A B,C BA CB A,B C,A C共经历7(=231)步。可以推知,移动 n 个盘子需要经历2 n 1。,5.4 函数的递归调用,解决方法:n=1时,直接把圆盘从A移到Cn1时,先把上面n-1个圆盘从A移到B,然后将n号盘从A移到C,再将n-1个盘从B移到C。即把求解n个圆盘的Hanoi问题转化为求解n-1个圆盘的Hanoi问题,依次类推,直至转化成只有一个圆盘的Hanoi问题,5.4 函数的递归调用,函数move完成将第k个盘子从A移动到Cmove(int no,char from,char to);no:盘子编号,from:源柱 to:目的柱函数hanoi完成将n个盘子从A移动到Chanoi(int n,char one,char two,char three)借助two将n个盘子从one移动到three,5.4 函数的递归调用,将n个盘子借助B从A移动到C,实现过程如下:函数调用 A one,B two,C three步骤1:hanoi(n-1,one,three,two);借助C柱子将n-1个盘子从A移到B 步骤2:move(n,one,three);将第n个盘子从A柱子移动到C柱子步骤3:hanoi(n-1,two,one,three);借助A柱子将n-1个盘子从B移到C,函数的递归调用,例5.12:汉诺塔:有A,B,C三个塔座,A上套有n个直径不同的圆盘,按直径从小到大叠放,形如宝塔,编号1,2,3n。要求将n个圆盘从A移到C,叠放顺序不变,移动中遵循下列原则:每次只能移一个圆盘圆盘可在三个塔座上任意移动任何时刻,每个塔座上不能将大盘压到小盘上,#include void move(int no,char from,char to)printf(Move%3d:%c-%cn,no,from,to);void hanoi(int n,char one,char two,char three)if(n=1)move(n,one,three);else hanoi(n-1,one,three,two);move(n,one,three);hanoi(n-1,two,one,three);void main()int n;printf(Input the number of diskes:);scanf(%d,5.4 函数的递归调用,5.5 调用与被调用函数间的数据传递,本节内容,调用与被调用函数间的地址传递,调用与被调用函数间的数值传递,调用与被调用函数间的数值传递,函数调用可以实现调用函数与被调用函数之间数据的传递。一般采用三种方式进行数据传递。return语句是其中一种方式,通过return语句可以将一个函数值返回到主调函数中;另外还可以使用全局变量在函数间传递多个数据,这将在后边详细介绍;使用最多的是借助形参和实参实现数据的传递。在C语言中,实参和形参之间的传递有两种方法:“值传递”和“地址传递”。,调用与被调用函数间的数值传递,5.5.1.1 普通变量作函数参数作为实参的变量在内存中占有存储空间,而形参只有在被调用时才分配空间,调用结束该空间就被释放。因此实参变量在调用时将其值传递给对应形参变量,此时形参变量具有和实参变量相同的值,执行被调函数中的语句,调用结束释放形参单元,返回主调函数。,调用与被调用函数间的数值传递,#include void fun(int x,int y)x+;y+;printf(x=%d,y=%d,x,y);main()int m,n;printf(please input m,n:);scanf(%d,%d,调用与被调用函数间的数值传递,5.5.1.2 一维数组元素作函数实参数组元素我们也可以看成是一个变量,它与普通变量并无区别。因此它作为函数实参时与普通变量是完全相同的,在发生函数调用时,可以把作实参的数组元素的值传送给形参,实现单向的值传送。,调用与被调用函数间的数值传递,#include void sort(int x,int y,int z)int temp;if(xy)temp=x;x=y;y=temp;if(xz)temp=x;x=z;z=temp;if(yz)temp=y;y=z;z=temp;printf(x=%d y=%d z=%dn,x,y,z);,调用与被调用函数间的数值传递,main()int a3,i;for(i=0;i3;i+)scanf(%d,调用与被调用函数间的地址传递,数组名表示该数组在内存中占用单元的起始地址,数组元素是一个具体类型的数据。当数组元素作函数参数时和一般变量没有区别。数组名是数组的地址,作为实参向被调用函数传递时,只传递数组的地址,而不是将整个数组元素都复制到函数中去,也就是说用数组名作为实参调用函数时,指向该数组第一个元素的指针传给被调函数。实际上形参和实参为同一数组,因此当形参数组发生变化时,实参数组也随之变化。5.5.2.1 一维数组名作为函数参数,调用与被调用函数间的地址传递,#include void sort(int b,int n);void printarr(int b);main()int a10=11,52,23,77,48,64,59,32,93,38;printf(Before sort:n);printarr(a);sort(a,10);printf(After sort:n);printarr(a);void printarr(int b10)int i;for(i=0;i10;i+)printf(%5d,bi);printf(n);,调用与被调用函数间的地址传递,void sort(int b,int n)int i,j,t;for(i=1;ibj+1)t=bj;bj=bj+1;bj+1=t;,调用与被调用函数间的地址传递,调用与被调用函数间的地址传递,用数组名作函数参数时还应注意以下几点:形参数组和实参数组的类型必须一致,否则将引起错误。形参数组和实参数组的长度可以不相同,因为在调用时,只传送首地址而不检查形参数组的长度。当形参数组的长度与实参数组不一致时,虽不至于出现语法错误(编译能通过),但程序执行结果可能与实际不符,这是应予以注意的。在函数形参表中,允许不给出形参数组的长度,或用一个变量来表示数组元素的个数。,调用与被调用函数间的地址传递,5.5.2.2 多维数组名作函数参数多维数组名作实参时对应的形参也应该定义成一个维数相同的数组形式。对形参数组定义时可以指定每一维的大小,也可以省略第一维的大小说明。因此,“int fun(int a310)”或“int fun(int a10)”这类写法都是合法的。,#include get_sum_row(int x 3,int result,int row,int col)int i,j;for(i=0;irow;i+)resulti=0;for(j=0;jcol;j+)resulti+=xij;main()int a23=3,6,9,1,4,7;int sum_row2,row=2,col=3,i;get_sum_row(a,sum_row,row,col);for(i=0;irow;i+)printf(The sum of row%d=%dn,i+1,sum_rowi);,调用与被调用函数间的地址传递,编写程序将矩阵转置。要求转置过程用独立的函数实现,且该函数的参数传递方式为地址传递。设转置前矩阵为a,转置后为矩阵b,如下所示:,调用与被调用函数间的地址传递,#include void turn(int arra 4,int arrb 3);main()int a34=1,2,3,4,5,6,7,8,9,10,11,12;int i,j,b43;turn(a,b);printf(array b:n);for(i=0;i4;i+)for(j=0;j3;j+)printf(%5d,bij);printf(n);,调用与被调用函数间的地址传递,void turn(int arra 4,int arrb 3)/矩阵转置函数 int r,c;for(r=0;r3;r+)for(c=0;c4;c+)arrbcr=arrarc;,调用与被调用函数间的地址传递,用数组名作函数参数与用数组元素作实参有几点不同:用数组元素作实参时,只要数组类型和函数的形参变量的类型一致,那么作为实参的数组元素的类型也和函数形参变量的类型是一致的。因此,并不要求函数的形参也是数组元素。用数组名作函数参数时,不是进行值的传送。因为实际上形参数组并不存在,编译系统不为形参数组分配内存。因此在数组名作函数参数时所进行的传送只是地址的传送,也就是说把实参数组的首地址赋予形参数组名。形参数组名取得该首地址之后,也就等于有了实在的数组。实际上是形参数组和实参数组为同一数组,共同拥有一段内存空间。,5.6 变量的作用域,本节内容,5.6.2 全局变量,5.6.1 局部变量,5.6 变量的作用域,变量的作用域是指变量的有效范围。形参变量只在被调用期间才分配内存单元,调用结束立即释放。这一点表明形参变量只有在函数内才是有效的,离开该函数就不能再使用了。这种变量有效性的范围称为变量的作用域。不仅对于形参变量,语言中所有的变量都有自己的作用域。变量说明的方式不同,其作用域也不同。语言中的变量,按作用域范围可分为两种,即局部变量和全局变量。,5.6.1 局部变量,局部变量也称为内部变量。是指在函数内部或复合语句内定义的变量以及形参。其作用域仅限于函数或复合语句内,离开该函数或复合语句后再使用这种变量就是非法的。,关于局部变量的作用域还要说明以下几点:主函数中定义的变量也只能在主函数中使用,不能在其它函数中使用。同时,主函数中也不能使用其它函数中定义的变量。因为主函数也是一个函数,它与其它函数是平行关系。形参变量是属于被调函数的局部变量,实参变量是属于主调函数的局部变量。允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的单元,互不干扰,也不会发生混淆。在复合语句中也可定义变量,其作用域只在复合语句范围内。,#include void sub();main()int a,b;a=3;b=4;printf(main:a=%d,b=%dn,a,b);sub();printf(main:a=%d,b=%dn,a,b);void sub()int a,b;a=6;b=7;printf(sub:a=%d,b=%dn,a,b);,#include void sub(int a,int b)/定义sub函数,有两个形参a,b int c;/定义变量ca=a+b;b=b+a;c=b-a;printf(sub:ta=%d b=%d c=%dn,a,b,c);main()int a=1,b=1,c=1;/main函数中定义变量a、b、c printf(main:ta=%d b=%d c=%dn,a,b,c);sub(a,b);int a=2,b=2;printf(comp:ta=%d b=%d c=%dn,a,b,c);printf(main:ta=%d b=%d c=%dn,a,b,c);,5.6.2 全局变量,全局变量也称为外部变量,它是在函数外部定义的变量。它不属于哪一个函数,而属于一个源程序文件。其作用域是从定义变量的位置开始到本源程序文件结束。在函数中使用全局变量,一般应作全局变量说明。只有在函数内经过说明的全局变量才能使用。全局变量的说明符为extern。,5.6.2 全局变量,对于全局变量有以下几点说明:全局变量的定义必须在所有的函数之外,且只能定义一次。其一般形式为:extern 类型说明符 变量名,变量名全局变量的说明应出现在使用该全局变量的各个函数内,一般形式为:extern 类型说明符 变量名,变量名,;但在一个函数之前定义的全局变量,在该函数内使用可不再加以说明。全局变量在定义时就已分配了内存单元,且一直占有内存单元直到该源文件结束。全局变量定义时可赋初始值,但在说明时不能再赋初始值,只是表明在函数内要使用某全局变量。,5.6.2 全局变量,#include void sub()extern int x;/在sub函数内说明全局变量xx+;/若没有对全局变量x进行说明,则无法使用printf(sub:%dn,x);extern int x=5;/定义全局变量xmain()sub();x=x+5;/在main函数内全局变量x无须说明,可直接使用printf(main:%dn,x);,5.6.2 全局变量,全局变量可加强函数模块之间的数据联系,但是又使函数依赖于这些变量,因而降低了函数的通用性、可靠性,可移植性。从模块化程序设计的观点来看这是不利的,因此在不必要时尽量不要使用全局变量。如果将所要传递的参数定义为全局变量,可使变量在整个程序中对所有函数都可见。这样相当于在调用函数和被调用函数之间实现了参数的传递和返回。实际中也经常使用这种方法,但定义全局变量必定长久地占用内存。因此,全局变量的数目要受到限制,特别对于较大的数组更是如此。在同一源文件中,允许全局变量和局部变量同名。在局部变量的作用域内,全局变量不起作用。,#include#define N 3#define M 5float aveN;/定义外部变量main()void aver(float stuM);float scoreNM;int i,j;printf(please input scores:);for(i=0;iN;i+)for(j=0;jM;j+)scanf(%f,5.6.2 全局变量,void aver(float stu5)int m,n;float sum;for(m=0;mN;m+)sum=0;for(n=0;nM;n+)sum+=stumn;avem=sum/5;/每人平均分保存在外部数组ave中,5.6.2 全局变量,#include main()void f(int x,int y);/函数f的说明extern int a;/全局变量a的说明int b=6,c=7;/定义局部变量b、cf(b,c);printf(%dt%dt%dn,a,b,c);int a=9,b=8;/定义局部变量a、b printf(%dt%dt%dn,a,b,c);c=10;printf(%dt%dt%dn,a,b,c);printf(%dt%dt%dn,a,b,c);printf(%dt%dt%dn,a,b,c);,5.6.2 全局变量,int a=5;/定义全局变量avoid f(int x,int y)/定义函数f int b,c;/定义局部变量b、cb=a+x;c=a-y;printf(%dt%dt%dn,a,b,c);,5.7 变量的存储类别,本节内容,5.7.2 自动变量,5.7.3 静态变量,5.7.4 外部变量,5.7.1 变量的存储方式与生存期,5.7.5 寄存器变量,5.7.1 变量的存储方式与生存期,存储类型是指变量占用内存空间的方式,也称为存储方式。变量的存储方式可分为“静态存储”和“动态存储”两种。静态存储变量通常是在变量定义时就分定存储单元并一直保持不变,直至整个程序结束。全局变量即属于此类存储方式。动态存储变量是指在程序执行过程中,使用它时才分配存储单元,使用完毕立即释放。典型的例子是函数的形式参数。,5.7.1 变量的存储方式与生存期,语言中变量的存储类型有以下四种:auto:自动变量register:寄存器变量extern:外部变量static:静态变量自动变量和寄存器变量属于动态存储方式,外部变量和静态变量属于静态存储方式。对一个变量的说明不仅应说明其数据类型,还应说明其存储类型。因此变量说明的完整形式应为:存储类型说明符 数据类型说明符 变量名,变量名;,5.7.2 自动变量,自动变量的类型说明符是auto。自动变量可省去说明符auto。在前面各章的程序中所定义的变量凡未加存储类型说明符的都是自动变量。自动变量具有以下特点:自动变量的作用域仅限于定义该变量的个体内。自动变量属于动态存储方式,只有在定义该变量的函数被调用时才给它分配存储单元,开始它的生存期。函数调用结束,释放存储单元,结束生存期。由于自动变量的作用域和生存期都局限于定义它的个体内(函数或复合语句内),因此不同的个体中允许使用同名的变量而不会混淆。,#include main()void prt(void);int x=1;int x=3;prt();printf(2nd x=%dn,x);/输出2nd x=3,复合语句内定义的x有效printf(1st x=%dn,x);/输出1st x=1,main函数内定义的x有效void prt(void)int x=5;printf(3th x=%dn,x);/输出3th x=5,prt函数内定义的x有效,5.7.3 静态变量,静态变量的类型说明符是static。静态变量属于静态存储方式,但属于静态存储方式的变量不一定就是静态变量,例如外部变量虽属于静态存储方式,但不一定是静态变量,必须由 static加以定义后才能成为静态外部变量,或称静态全局变量。而自动变量,通常属于动态存储方式,但是也可以用static将它定义为静态自动变量,或称静态局部变量,从而成为静态存储方式。由此看来,一个变量可由static进行再说明,并改变其原有的存储方式。,5.7.3 静态变量,局部变量的说明前再加上static说明符就构成静态局部变量,属于静态存储方式,它具有以下特点:静态局部变量在函数内定义,但不像自动变量那样,调用时就存在,退出函数时就消失。静态局部变量始终存在着,也就是说它的生存期为整个源程序。允许对静态局部变量赋初值,若在说明时未赋以初值,则系统自动赋予0值,而自动变量若不赋初值,其值是不确定的。静态局部变量的作用域与自动变量相同,即只

    注意事项

    本文(《c语言程序设计基础》5函数.ppt)为本站会员(牧羊曲112)主动上传,三一办公仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一办公(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    备案号:宁ICP备20000045号-2

    经营许可证:宁B2-20210002

    宁公网安备 64010402000987号

    三一办公
    收起
    展开