《c语言程序设计教学》第7章函数课件_第1页
《c语言程序设计教学》第7章函数课件_第2页
《c语言程序设计教学》第7章函数课件_第3页
《c语言程序设计教学》第7章函数课件_第4页
《c语言程序设计教学》第7章函数课件_第5页
已阅读5页,还剩115页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第7章 函数第1页,共120页。主要内容 模块化程序设计 函数的定义 向函数传递值和从函数返回值 函数的调用 函数的作用域和存储类别 第2页,共120页。为什么要用函数?问题: 如果程序的功能比较多,规模比较大,把所有代码都写在main函数中,就会使主函数变得庞杂、头绪不清,阅读和维护变得困难 有时程序中要多次实现某一功能,就需要多次重复编写实现此功能的程序代码,这使程序冗长,不精炼第3页,共120页。 在设计一个较大的程序时,往往把它分为若干个程序模块,每一个模块包括一个或多个函数,每个函数实现一个特定的功能 采用“分而治之”的办法简化程序设计的过程 C程序可由一个主函数和若干个其他函数构成

2、 事先编好一批实现各种不同功能的函数 主函数调用其它函数,其它函数也可以互相调用 同一个函数可以被一个或多个函数调用任意多次用模块化程序设计第4页,共120页。mainabcfghdeie第5页,共120页。 功能分解 自顶而下、逐步求精的过程 模块化分解原则 保证模块的相对独立性 高聚合(模块的功能独立、单一)、低耦合(模块对外接口简单) 设计好模块接口 接口是指罗列出一个模块的所有与外部打交道的变量 定义好后不要轻易改动 在模块开头(文件的开头)进行函数声明模块化程序设计方法第6页,共120页。 *How do you do! *例:输出以下的结果,用函数调用实现。第7页,共120页。 在

3、输出的文字上下分别有一行“*”号,显然不必重复写这段代码,用一个函数printstar来实现输出一行“*”号的功能 再写一个print_message函数来输出中间一行文字信息 用主函数分别调用这两个函数解题思路:第8页,共120页。例:函数调用的简单例子# include void main() void printstar(); /*对printstar函数声明*/ void print_message(); /*对print_message函数声明*/ printstar(); /*调用printstar函数*/ print_message(); /*调用print_message函数*

4、/ printstar(); /*调用printstar函数*/ 第9页,共120页。void printstar() /*定义printstar函数*/ printf(* * * * * * * * * * * * * * * *n);void print_message() /*定义print_message函数*/ printf(How do you do!n); 运行情况如下:* * * * * * * * * * * * * * * *How do you do!* * * * * * * * * * * * * * * *第10页,共120页。(1)一个C程序由一个或多个程序模块组

5、成,每一个程序模块作为一个源程序文件。对较大的程序,一般不希望把所有内容全放在一个文件中,而是将它们分别放在若干个源文件中,由若干个源程序文件组成一个C程序。这样便于分别编写、分别编译,提高调试效率。一个源程序文件可以为多个C程序共用。 说明:第11页,共120页。(2) 一个源程序文件由一个或多个函数以及其他有关内容(如命令行、数据定义等)组成。一个源程序文件是一个编译单位,在程序编译时是以源程序文件为单位进行编译的,而不是以函数为单位进行编译的。(3) C程序的执行是从main函数开始的,如果在main函数中调用其他函数,在调用后流程返回到main函数,在main函数中结束整个程序的运行。

6、第12页,共120页。(4)所有函数都是平行的,即在定义函数时是分别进行的,是互相独立的。一个函数并不从属于另一函数,即函数不能嵌套定义。函数间可以互相调用,但不能调用main函数。main函数是系统调用的。第13页,共120页。(5)从用户使用的角度看,函数有两种: 标准函数,即库函数。这是由系统提供的,用户不必自己定义这些函数,可以直接使用它们。不同的C系统提供的库函数的数量和功能会有一些不同,但许多基本的函数是共同的。 用户自己定义的函数。用以解决用户的专门需要。 第14页,共120页。(6) 从函数的形式看,函数分两类: 无参函数。无参函数一般用来执行指定的一组操作。在调用无参函数时,

7、主调函数不向被调用函数传递数据。有参函数。主调函数在调用被调用函数时,通过参数向被调用函数传递数据。 第15页,共120页。怎样定义函数?为什么要定义函数定义函数的方法第16页,共120页。 C语言要求,在程序中用到的所有函数,必须“先定义,后使用” 指定函数名字、函数返回值类型、函数实现的功能以及参数的个数与类型,将这些信息通知编译系统。第17页,共120页。 指定函数的名字,以便以后按名调用 指定函数类型,即函数返回值的类型 指定函数参数的名字和类型,以便在调用函数时向它们传递数据 指定函数的功能。这是最重要的,这是在函数体中解决的第18页,共120页。 对于库函数,程序设计者只需用#in

8、clude指令把有关的头文件包含到本文件模块中即可 程序设计者需要在程序中自己定义想用的而库函数并没有提供的函数第19页,共120页。 函数定义的一般形式 (1)无参函数的定义一般形式(2)有参函数定义的一般形式(3)空函数 第20页,共120页。 函数定义的一般形式 (1)无参函数的定义一般形式 类型函数名() 声明部分 语句部分类型标识符指明函数类型,函数的类型实际上是函数返回值的类型。函数名后面有一个空括号,其中无参数,但是括号不能少。类型函数名(void) 声明部分 语句部分第21页,共120页。例如:void hello() printf(“hello world!n”);第22页,

9、共120页。(2)有参函数定义的一般形式 类型函数名(类型 形式参数1,类型 形式参数2,) 声明部分 语句部分有参函数比无参函数多了形式参数列表,它们可以是各种类型的变量,个参数之间用逗号间隔。进行函数调用时,主调函数将赋予这些形式参数实际的值,形参是变量,必须在形参表中给出形参的类型说明例如:int max(int x, int y) int z; / *函数体中的声明部分*/ z=xy?x:y; return (z);第23页,共120页。 (3)空函数 类型函数名(形参列表) 例如: Dummy(形参列表) 先用空函数占一个位置,以后逐步扩充 好处:程序结构清楚,可读性好,以后扩充新功

10、能方便,对程序结构影响不大第24页,共120页。调用函数函数的调用形式函数调用时的数据传递函数调用的过程函数的返回值第25页,共120页。函数调用的形式 函数调用的一般形式为:函数名(实参表列) 如果是调用无参函数,则“实参表列”可以没有,但括号不能省略 如果实参表列包含多个实参,则各参数间用逗号隔开。第26页,共120页。按函数调用在程序中出现的形式来分,可以有以下3种函数调用方式:(1)函数调用语句 把函数调用单独作为一个语句 如:printfstar();这时不要求函数带回值,只要求函数完成一定的操作第27页,共120页。(2)函数表达式 函数调用出现在另一个表达式中 如:c=2*max

11、(a,b); 这时要求函数带回一个确定的值以参加表达式的运算(3)函数参数 函数调用作为另一函数调用时的实参 如:mmax(a,max(b,c); 其中max(b,c)是一次函数调用,它的值作为max另一次调用的实参第28页,共120页。 函数参数:用于函数间数据的传递 形式参数(形参):定义函数时给出的参数 实际参数(实参):调用函数时给出的参数 实参与形参的个数应相等,类型应匹配。实参与形参按顺序对应,一一传递数据。 如果实参列表包括多个实参,对实参求值的顺序并不是确定的,有的系统按自左至右顺序求实参的值,有的系统则按自右至左顺序。说明:第29页,共120页。例 : 实参求值的顺序如果按自

12、左至右顺序求实参的值,则函数调用相当于f(2,3) 如果按自右至左顺序求实参的值,则函数调用相当于f(3,3) 第30页,共120页。函数调用时的数据传递 形式参数:函数名后面括号中的变量名称为“形式参数”(简称“形参”)。 实际参数:主调函数中调用一个函数时,函数名后面括号中的参数(可以是一个表达式)称为“实际参数”(简称“实参”)。第31页,共120页。 实参和形参间的数据传递 在调用函数过程中,系统会把实参的值传递给被调用函数的形参 该值在函数调用期间有效,可以参加被调函数中的运算用return语句返回计算结果,通过函数调用使主调函数得到的确定值。第32页,共120页。例: 调用函数时的

13、数据传递运行情况如下:,max is 第33页,共120页。通过函数调用,可使两个函数中的数据发生联系。第34页,共120页。函数调用的过程 在定义函数中指定的形参,在未出现函数调用时,它们并不占内存中的存储单元。在发生函数调用时,函数max的形参被临时分配内存单元。 调用结束,形参单元被释放 实参单元仍保留并维持原值,没有改变 如果在执行一个被调用函数时,形参的值发生改变,不会改变主调函数的实参的值第35页,共120页。关于形参与实参的说明:(1) 在定义函数中指定的形参,在未出现函数调用时,它们并不占内存中的存储单元。只有在发生函数调用时,函数max中的形参才被分配内存单元。在调用结束后,

14、形参所占的内存单元也被释放。(2) 实参可以是常量、变量或表达式, 例如: max (3,a+b); 但要求它们有确定的值。在调用时将实参的值赋给形参。第36页,共120页。(3)在被定义的函数中,必须指定形参的类型。(4)实参与形参的类型应相同或赋值兼容。(5)值传递:实参向形参的数据传递是单向“值传递”,只能由实参传给形参,而不能由形参传回来给实参。 在调用函数时,给形参分配存储单元,并将实参对应的值传递给形参,调用结束后,形参单元被释放,实参单元仍保留并维持原值。第37页,共120页。函数的返回值说明: (1)函数的返回值是通过函数中的return语句获得的。一个函数中可以有一个以上的r

15、eturn语句,执行到哪一个return语句,哪一个语句起作用。 return语句后面的括弧也可以不要 例如: “return z;” 等价于 “ return (z);” return后面的值可以是一个表达式。 例如: max(int x,int y) return(?:); 第38页,共120页。(2)函数的返回值应当属于某一个确定的类型,在定义函数时指定函数返回值的类型。例如:下面是3个函数的首行:int max(float x,float y) /* 函数值为整型 */char letter(char c1,char c2) /* 函数值为字符型 */ double min(int x

16、,int y) /* 函数值为双精度型 */ 注意:凡不加类型说明的函数,自动按整型处理。第39页,共120页。(3)在定义函数时指定的函数类型一般应该和return语句中的表达式类型一致。如果函数值的类型和return语句中表达式的值不一致,则以函数类型为准。对数值型数据,可以自动进行类型转换。即函数类型决定返回值的类型。(4)对于不带回值的函数,应当用“void”定义函数为“无类型”(或称“空类型”)。此时在函数体中不得出现return语句。 第40页,共120页。例: 返回值类型与函数类型不同运行情况如下:1.5, 2.5max is 2 1.52.62.62变为2第41页,共120页。

17、main()函数 main()函数是由系统调用的,使得C程序从main()函数开始执行,调用其它函数后流程返回到main()函数,在main()中结束整条程序的运行。若定义main()时没有指定返回值类型,也没有使用void,则返回值默认为int类型,虽然语法允许这样做,但实际编程时通常将main()函数写成如下形式:第42页,共120页。第一种形式:用void指明函数没有返回值第二种形式:return返回值的0等价于调用exit()时提供的参数。第三种形式:进一步用void指出main函数没有参数第43页,共120页。在一个函数中调用另一函数(即被调用函数)需要具备哪些条件呢 ? 首先被调用

18、的函数必须是已经存在的函数(是库函数或用户自己定义的函数)。但光有这一条件还不够。 如果使用库函数,还应该在本文件开头#include 命令将调用有关库函数时所需用到的信息“包含”到本文件中来。 如果使用用户自己定义的函数,而该函数的位置在调用它的函数(即主调函数)的后面,应该在主调函数中对被调用的函数作声明。第44页,共120页。例:对被调用的函数作声明# include void main() float add(float x, float y); /*对被调用函数的声明*/ float a,b,c; scanf(f,f,&a,&b); cadd(a,b); printf(sum is

19、f n,c);float add(float x,float y) /*函数定义*/ float z; /* 函数体 */ zxy; return(z);第45页,共120页。例:对被调用的函数作声明# include float add(float x,float y) /*函数定义*/ float z; /* 函数体 */ zx+y; return (z);void main() float a,b,c; scanf(“%f,%f,&a,&b); cadd(a,b); printf(sum is %f n,c);第46页,共120页。 函数原型的一般形式为: 1. 函数类型 函数名(类型1

20、,类型2,); 2. 函数类型 函数名(类型1,参数1,参数2,参数2,); 如: float add(float x, float y); float add(float, float); 在调用函数时,需要进行函数原型声明第47页,共120页。声明的作用:是把函数名、函数参数的个数和参数类型等信息通知编译系统,以便在遇到函数调用时,编译系统能正确识别函数并检查调用是否合法。第48页,共120页。注意:函数的“定义”和“声明”的区别: 函数的定义是指对函数功能的确立,包括指定函数名,函数值类型、形参及其类型、函数体等,它是一个完整的、独立的函数单位。 函数的声明的作用则是把函数的名字、函数类

21、型以及形参的类型、个数和顺序通知编译系统,以便在调用该函数时系统按此进行对照检查。 第49页,共120页。函数小结第50页,共120页。第51页,共120页。第52页,共120页。第53页,共120页。第54页,共120页。第55页,共120页。第56页,共120页。函数的嵌套调用和递归调用 嵌套调用:在定义一个函数时,其函数体内又包含另一个函数的完整定义 。 递归调用:在调用一个函数的过程中又出现直接或间接地调用该函数本身。第57页,共120页。解题思路:main中调用max4函数,找4个数中最大者max4中再调用max2,找两个数中的大者max4中多次调用max2,可找4个数中的大者,然后

22、把它作为函数值返回main函数main函数中输出结果例: 输入4个整数,找出其中最大的数。用函数的嵌套调用来处理。 第58页,共120页。#include int main() int max4(int a,int b,int c,int d); /*对被调用函数max4的声明*/ int a,b,c,d,max; printf(“4 interger numbers:); scanf(%d,%d,%d,%d,&a,&b,&c,&d); max=max4(a,b,c,d); printf(max=%d n, max); return 0; 第59页,共120页。int max4(int a,i

23、nt b,int c,int d) /*max4函数*/ int max2(int a,int b); /*对被调用函数max2的声明*/ int m; m=max2(a,b); /*a,b中较大者*/ m=max2(m,c); /*a,b,c中较大者*/ m=max2(m,d); /*a,b,c,d中较大者*/ return(m); int max2(int a,int b) /*max2函数*/ if(a=b) return a; else return b; return(ab?a:b);第60页,共120页。int max4(int a,int b,int c,int d) /*max

24、4函数*/ int max2(int a,int b); /*对被调用函数max2的声明*/ int m; m=max2(a,b); /*a,b中较大者*/ m=max2(m,c); /*a,b,c中较大者*/ m=max2(m,d); /*a,b,c,d中较大者*/ return(m); int max2(int a,int b) /*max2函数*/ return (ab?a:b); m=max2(max2(a,b),c);m=max2(max2(max2(a,b),c),d);return (max2(max2(max2(a,b),c),d);第61页,共120页。#include in

25、t main() int max4(int a,int b,int c,int d); /*对被调用函数max4的声明*/ int a,b,c,d,max; printf(“4 interger numbers:); scanf(%d,%d,%d,%d,&a,&b,&c,&d); max=max4(a,b,c,d); printf(max=%d n, max); return 0;int max4(int a,int b,int c,int d) /*max4函数*/ int max2(int a,int b); return (max2(max2(max2(a,b),c),d); int m

26、ax2(int a,int b) /*max2函数*/ return (ab?a:b); 第62页,共120页。int max2(int a,int b) /*max2函数*/ return ab?a:b; int max4(int a,int b,int c,int d) /*max4函数*/ return max2(max2(max2(a,b),c),d); #include int main() int a,b,c,d,max; printf(4 interger numbers:); scanf(%d,%d,%d,%d,&a,&b,&c,&d); max=max4(a,b,c,d);

27、printf(max=%dn, max); return 0;第63页,共120页。例:函数递归 有5个人坐在一起,问第5个人多少岁?他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。问第3个人,又说比第2个人大2岁。问第2个人,说比第1个人大2岁。最后问第1个人,他说是10岁。请问第5个人多大。 解题思路: 要求第5个年龄,就必须先知道第4个年龄 要求第4个年龄必须先知道第3个年龄 第3个年龄又取决于第2个年龄 第2个年龄取决于第1个年龄 每个学生年龄都比其前1个学生的年龄大2第64页,共120页。age(5)= age (4)+2age(4)= age (3)+2age(3)=

28、age (2)+2age(2)= age (1)+2age(1)= 10用数学公式表述如下:age(n)= 10 ()age(n-1)+2 ()第65页,共120页。 age(5)=age(4)+2 age(4)=age(3)+2 age(3)=age(2)+2 age(2)=age(1)+2 age(1) =10 age(2) =12 age(3) =14 age(4) =16 age(5) =18 回溯阶段 递推阶段结束递归的条件第66页,共120页。可以用一个函数来描述上述递归过程:int age(int n) /求年龄的递归函 int c; /c用作存放函数的返回值的变量 if(n=1

29、) c=10; else c=age(n-1)+2; return c;运行结果如下:18 用一个主函数调用age函数,求得第5人的年龄。#include int main() printf(%d,age(5); return 0;第67页,共120页。例:用递归方法求!解题思路:求n!也可以用递归方法,即5!等于4!5,而4!=3!4,!=可用下面的递归公式表示:!第68页,共120页。#include int main() int fac(int n); int n, y; printf(input an integer number:); scanf(%d,&n); y=fac(n);

30、printf(%d!=%dn,n,y); return 0;int fac(int n) int f; if(n0) printf(n0,data error!); else if(n=0 | | n=1) f=1; else f=fac(n-1)*n; return(f); 注意溢出第69页,共120页。 局部变量和全局变量 语句块:程序中被括起来的语句。 作用域:每个变量仅在定义它的语句块内有效,并且拥有自己的存储空间 同一个语句块内不可以定义同名变量,不同语句块内可以定义同名变量第70页,共120页。 在函数内部或复合语句内部定义的变量称为“局部变量”。 在一个函数内部定义的变量只在本函

31、数范围内有效 在复合语句内定义的变量只在本复合语句范围内有效局部变量:第71页,共120页。例:float f1( int a) /*函数f1 */ int b,c; /* a、b、c有效*/ char f2(int x,int y) /*函数f2 */ int i,j; /* x、y、i、j有效*/ void main( ) /*主函数*/ int m,n; /* m、n有效*/ 第72页,共120页。例:float f1( int a) int b,c; char f2(int x,int y) int i,j; int main( ) int a,b; return 0; a、b也仅在此

32、函数内有效类似于不同班同名学生第73页,共120页。主函数中定义的变量只在主函数中有效,而不因为在主函数中定义而在整个文件或程序中有效。主函数也不能使用其他函数中定义的变量。不同函数中可以使用相同名字的变量,它们代表不同的对象,互不干扰。形式参数也是局部变量。进入语句块时获得内存,仅能由语句块内语句访问,退出语句块时释放内存,不在有效。说明:第74页,共120页。 全局变量 在函数内定义的变量是局部变量,而在函数之外定义的变量称为外部变量 外部变量是全局变量(也称全程变量) 全局变量可以为本文件中其它函数所共用 有效范围为从定义变量的位置开始到本源文件结束从程序运行起即占据内存,程序运行过程中

33、可以随时访问,程序退出时释放内存第75页,共120页。int p=1,q=5; /* 外部变量 */float f1(int a) /* 定义函数f1 */ int b, c; char c1,c2; /* 外部变量*/char f2 (int x, int y) /* 定义函数f2 */ int i,j; 全局变量p,q的作用范围 全局变量c1,c2的作用范围void main ( ) /*主函数*/ int m,n; p、q的有效范围c1、c2的有效范围第76页,共120页。建议:不必要时不要使用全局变量,原因如下: 全局变量在程序的全部执行过程中都占用存储单元,而不是仅在需要时才开辟单元

34、。 使用全局变量过多,会降低程序的清晰性。在各个函数执行时都可能改变外部变量的值,程序容易出错。因此,要限制使用全局变量。第77页,共120页。降低函数的通用性。因为函数在执行时要依赖于其所在的外部变量。如果将一个函数移到另一个文件中,还要将有关的外部变量及其值一起移过去。但若该外部变量与其他文件的变量同名时,就会出现问题,降低了程序的可靠性和通用性。一般要求把C程序中的函数做成一个封闭体,除了可以通过“实参形参”的渠道与外界发生联系外,没有其他渠道。第78页,共120页。例 外部变量与局部变量同名#include int a=3,b=5; /* a,b为外部变量*/void main ( )

35、 int max(int a,int b); int a=8; /*a为局部变量 */ printf (%d, max (a,b); /*全局变量b的作用范围*/max (int a, int b) /*a,b为局部变量 */ int c; c=ab?ab; 形参a、b作用范围 return (c); 运行结果为 8 第79页,共120页。分析:设置两个函数f、fact。f用于求平方fact用于求阶乘第80页,共120页。第81页,共120页。 变量的存储类型 从变量的作用域(即从空间)角度来分,可以分为全局变量和局部变量。 从变量值存在的时间角度来分,又可以分为静态存储方式和动态存储方式。静

36、态存储方式:指在程序运行期间由系统分配固定的存储空间的方式。动态存储方式:在程序运行期间根据需要进行动态的分配存储空间的方式。第82页,共120页。程序区静态存储区动态存储区用户存储空间可以分为三个部分:将数据存放在此区全局变量全部存放在静态存储区中函数形式参数函数中定义的没有用关键字static声明的变量函数调用时的现场保护和返回地址等存放在动态存储区程序开始执行时给全局变量分配存储区,程序执行完毕就释放。在程序执行过程中占据固定的存储单元函数调用开始时分配,函数结束时释放。在程序执行过程中,这种分配和释放是动态的第83页,共120页。 全局变量全部存储在静态存储区中,在程序开始执行时给全局

37、变量分配存储区,程序执行完毕就释放。在程序执行过程中占据固定的存储单元。 动态存储区中存放以下数据:函数形式参数、自动变量、函数调用时的返回值等。对这些数据,在函数调用开始时分配动态存储空间,函数结束时释放这些空间,在程序执行过程中,这种分配和释放是动态的,如果在一个程序中,两次调用同一函数,分配给此函数中局部变量的存储空间地址可能是不相同的。第84页,共120页。变量的基本属性:变量名、变量类型、变量值变量的其它属性: 作用域:程序中可引用该变量的区域 存储类别:变量存储在哪里 存储期:变量存活期第85页,共120页。 变量作用域即可以引用该变量的程序段 C语言中变量可以在三种位置进行定于:

38、函数内部的定于部分函数内部的某一个复合语句内部所有函数之外变量定义的位置决定了变量的作用域 以上三种位置的变量分别对应于:函数作用域 块作用域文件作用域 在一个函数内部定于的变量成为局部变量。在所有函数之外定义的变量成为全局变量。变量作用域第86页,共120页。函数作用域:若变量在函数内所有语句之前定义,则该变量具有函数作用域,只有在定义变量的函数内部才能使用这些变量。 块作用域:若变量在复合语句中定义,则其具有块作用域,只在复合语句范围内才能引用该变量。文件作用域 。文件作用域:若变量在函数外定义,则该变量具有文件作用域,从变量定义位置开始,到本文件结束为止的区域可以引用该变量。 第87页,

39、共120页。 说明:同一文件中,允许全局变量和局部变量同名,在局部变量的作用域内,外部变量将被屏蔽不起作用。 允许函数定义部分定义的变量与该函数内部的复合语句中定义的变量同名。在复合语句执行时,哈数定义部分定义的变量是“隐藏的”,直到复合语句结束。建议:尽量不要这么做,系统不会混淆,但并不意味着人也不会混淆。第88页,共120页。例 外部变量与局部变量同名#include int a=3,b=5; /* a,b为外部变量*/void main ( ) int max(int a,int b); int a=8; /*a为局部变量 */ printf (%d, max (a,b); /*全局变量

40、b的作用范围*/max (int a, int b) /*a,b为局部变量 */ int c; c=ab?ab; 形参a、b作用范围 return (c); 运行结果为 8 第89页,共120页。第90页,共120页。存储类别包括:自动(auto)静态(static)寄存器(register)外部(extern)变量的存储类别与变量的作用域和生存期等信息存在一定的联系变量的存储类别第91页,共120页。(1)自动变量(auto变量) 定义格式: auto 类型名 变量名; (auto可有可无) 如果不专门声明存储类别,都是动态地分配存储空间的。 函数中的形参和在函数中定义的变量(包括在复合语句

41、中定义的变量),都属此类。在调用该函数时系统会给它们分配存储空间,在函数调用结束时就自动释放这些存储空间。因此,这类局部变量称为自动变量。第92页,共120页。第93页,共120页。第94页,共120页。(2)静态变量(static变量) 定义格式:static 类型名 变量名; 局部变量和全局变量都可以定义为static存储类别的变量。 具有静态存储类别的局部变量称为静态局部变量 具有静态存储类别的全局变量成为静态全局变量第95页,共120页。(空字符);第96页,共120页。第97页,共120页。 全局变量具有全局作用域。全局变量只需在一个源文件中定义,就可以作用于所有的源文件。当然,其他

42、不包含全局变量定义的源文件需要用extern 关键字再次声明这个全局变量。 静态全局变量与全局变量的区别在于如果程序包含多个文件的话,它作用于定义它的文件里,不能作用到其它文件里,即被static关键字修饰过的变量具有文件作用域。这样即使两个不同的源文件都定义了相同名字的静态全局变量,它们也是不同的变量。全局变量和静态全局变量:第98页,共120页。第99页,共120页。注意:局部变量改为静态局部变量后, 改变了它的生存期,但作用域未变全局变量改为静态全局变量后,改变了它的作用域,但是生存期未变第100页,共120页。例:输出1到5的阶乘值#include void main () int f

43、ac (int n); int ; for(i=1; i=5;i+) printf (%d!=dn, i, fac (i);int fac (int n) static int f=1; f=f*n; return (f);第101页,共120页。例:考察静态局部变量的值#include void main() int f(int); int a=2, i; for(i=0; i3; i+) printf(%d”, f(a);int f(int a) auto int b=0; static c=3; b=b+1; c=c+1; return (a+b+c);调用三次每调用一次,开辟新a和b,

44、但c不是第一次调用开始:3bc第一次调用期间:bc第一次调用结束:c0144第二次调用开始:4bc第二次调用期间:bc第二次调用结束:c0155第三次调用开始:5bc第三次调用期间:bc第三次调用结束:c0166f(a) 7f(a) 8f(a) 9第102页,共120页。()寄存器变量(register变量) 定义格式:register 类型名 变量名; 一般情况下,变量的值是存放在内存中的。当程序中用到哪一个变量的值时,由控制器发出指令将内存中该变量的值送到运算器中。 经过运算器进行运算,如果需要存数,再从运算器将数据送到内存存放。 第103页,共120页。 但是,如果有一些变量使用频繁,则

45、为存取变量的值要花费不少时间。为提高执行效率,C语言允许将局部变量的值放在CPU中的寄存器中,需要用时直接从寄存器取出参加运算,不必再到内存中去存取。由于对寄存器的存取速度远高于对内存的存取速度,因此这样做可以提高执行效率。这种变量叫做寄存器变量,用关键字register作声明。第104页,共120页。第105页,共120页。例:使用寄存器变量#include void main () long fac(long); long i,n; scanf(%ld,&n); for(i=1;i=n;i+) printf(%ld!=%ldn,i,fac(i);long fac(long n) regis

46、ter long i,f=1; /*定义寄存器变量*/ for (i=1;i=n;i+) f=f*i; return (f);第106页,共120页。对寄存器变量的说明: 只有局部自动变量和形式参数可以作为寄存器变量,其它(全局变量)不行。 局部静态变量不能定义为寄存器变量 例如:register static int a,b; 错误 一个计算机系统不能定义任意多个寄存器变量,不同系统允许使用的寄存器个数是不同的。第107页,共120页。 定义格式:extern 类型名 变量名; 具有外部存储类型的全局变量又称非静态全局变量(4)外部变量(extern变量)5.若定义而没有初始化,则自动赋值为0第108页,共120页。 用extern来声明外部变量,以扩展外部变量的作用域。1. 在一个文件内扩展外部变量的作用域 如果在定义点之前的函数想引用该外部变量,则应该在引用之前用关键字extern对该变量作“外部变量声明”,这样可以从“声明”处起,合法地使用该外部变量。第109页,共120页。例:用extern声明外部变量,扩展它在程序文件中的作用域#include void main() int max(int,int

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论