第7章 函数(课件)-《C语言程序设计(第四版)》同步教学(清华大学出版)

2024-09-19
| 31页
| 158人阅读
| 22人下载
普通

内容正文:

7.1 函数概述 7.2 函数的声明 7.3 函数定义和函数调用 7.4 程序举例 7.5 函数的嵌套调用和递归调用 7.6 变量的作用域 7.7 变量的存储类别 7.1 函数概述 模块化程序设计 基本思想:将一个大的程序按功能分割成一些小模块。 特点: 各模块相对独立、功能单一、结构清晰、接口简单 控制了程序设计的复杂性 缩短开发周期 避免程序开发的重复劳动 易于维护和功能扩充 开发方法: 自上向下,逐步分解,分而治之 > < 【例7.1】 计算5!+6!+7!并输出结果。 #include <stdio.h> main( ) { int i,t,num1=5,num2=6,num3=7,sum=0; for (i=1,t=1;i<=num1;i++) t=t*i; sum=sum+t; for (i=1,t=1;i<=num2;i++) t=t*i; sum=sum+t; for (i=1,t=1;i<=num3;i++) t=t*i; sum=sum+t; printf("5!+6!+7!=%d ",sum); } 出现重复 > < #include <stdio.h> int fac( int num); main( ) { int t1,t2,t3,sum=0; t1=fac(5); t2=fac(6); t3=fac(7); sum=t1+t2+t3; printf("5!+6!+7!=%d ",sum); } int fac( int num) /* 定义fac函数,num是形参 */ { int i,t; for(i=1,t=1;i<=num;i++) t=t*i; return t; /* 函数的返回值 */ } > < 7.2 函数的声明 函数声明的一般形式如下: 类型标识符 函数名(类型 形参名1, 类型 形参名2,…); 或 类型标识符 函数名(类型, 类型,…); #include <stdio.h> int fac( int num); /* 对函数fac的声明语句 */ main( ) { ... } > < 7.3 函数定义和函数调用 函数类型 函数名(形参类型说明表) { 说明部分 语句部分 } 函数定义: > < 函数的调用 调用形式 函数名(实参表); 说明: 实参与形参个数相等,类型一致,按顺序一一对应 实参表求值顺序,因系统而定 > < #include <stdio.h> int max(int a,int b); /* 函数原型的声明 */ int main( ) { int x,y,z; printf("input two numbers: "); scanf("%d%d",&x,&y); z=max(x,y); /* 函数的调用语句 */ printf("maxmum=%d",z); return 0; } /*以下是函数的定义部分*/ int max(int a,int b) { if(a>b) return a; else return b; } 实参 形参 > < 7.5 函数的嵌套调用和递归调用 7.5.1嵌套调用 C规定:函数定义不可嵌套,但可以嵌套调用函数 例7.7输入两个整数,输出较大值 的函数调用过程如下图所示。 > < 7.5.2 函数的递归调用 递归是一种特殊的解决问题的方法。其基本思想是:将要解决的问题分解成比原问题规模小的类似子问题,而解决这个类似子问题时,又可以用到原有问题的解决方法,按照这一原则,逐步递推转化下去,最终将原问题转化成较小且有已知解的子问题。 (1)递推阶段:将原问题不断地转化成子问题,逐渐从未知向已知推进,最终到达已知解的问题,递推阶段结束。 (2)回归阶段:从已知解的问题出发,按照递推的逆过程,逐一求值回归,最后到达递归的开始处,结束回归阶段,获得问题的解。 例如:求5! 递推阶段5!=5×4!→4!=4×3!→3!=3×2!→2!=2×1!→1!停止,其中1!=1 回归阶段5!=5×4!=120←4!=4×3!=24←3!=3×2!=6←2!=2×1!=2←1!=1 > < > < 例 : 有5个人坐在一起,问第5个人多少岁?他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。问第3个人,又说比第2个人大2岁。问第2个人,说比第1个人大2岁。最后问第1个人,他说是10岁。请问第5个人多大。 age(5)= age (4)+2 age(4)= age (3)+2 age(3)= age (2)+2 age(2)= age (1)+2 age(1)= 10 用数学公式表述如下: age(n)= 10 (n=1) age(n-1)+2 (n>1) > < age(5) c=age(4)+2; return c; age(int n) { int c; if (n==1) c=10; else c=age(n-1)+2; return c; } 递归过程 跟踪分析: age(4) c=age(3)+2; return c; age(3) c=age(2)+2; return c; age(2) c=age(1)+2; return c; age(1) c=10 return c; c=10 c=12 c=14 c=16 c=18 7.6 变量的作用域 7.6.1 局部变量 1、定义:在一个函数(或复合语句) 内部定义的变量。 2、作用域:本函数(或复合语句) 它只在本函数范围(或复合语句)内有效,也就是说只有在本函数(或复合语句)内才能使用它们,在此函数以外是不能使用这些变量的。 > < 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有效 3、说明 (1)形式参数是局部变量。 如f1中形参a,出了f1函数就无效。 (2)main中定义的变量只在main中有效,也是局部变量。 不能因为在main函数中定义就在整个文件或程序中有效。 main函数也不能使用其它函数中定义的变量。 > < 例 不同函数中同名变量 main() { int a,b; a=3; b=4; printf("main:a=%d,b=%d ",a,b); sub(); printf("main:a=%d,b=%d ",a,b); } sub() { int a,b; a=6; b=7; printf("sub:a=%d,b=%d ",a,b); } 运行结果: main:a=3,b=4 sub:a=6,b=7 main:a=3,b=4 3、说明 (3)不同函数中的同名变量,占有不同内存单元,因此不会相互影响 > < 3、说明 (4)复合语句中的变量 运行结果:5 4 3 2 1 例 复合语句中变量 #define N 5 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]); } 变量temp只在本复合语句中有效,离开该复合语句就无效,释放内存。 > < 1、定义:在所有函数外部定义的变量。 全局变量可以为本文件中其他函数所共用。 2、作用域:从定义变量的位置开始到本源文件结束,及有 extern说明的其它源文件。 7.6.2 全局变量 > < 3、说明: (1)有效范围:从定义或有extern声明的位置开始,直至它所在源程序文件的结束。 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的作用范围 > < 3、说明: (2) 若外部变量与局部变量同名,则外部变量被屏蔽 int a=3,b=5; max(int a, int b) { int c; c=a>b?a:b; return(c); } main() { int a=8; printf("max=%d",max(a,b)); } 例 外部变量与局部变量 运行结果:max=8 > < 内存 ……. main() { int a; a=10; printf(“%d”,a); } 编译或函数调用时为其分配内存单元 10 2000 2001 程序中使用变量名对内存操作 在C语言中每一个变量和函数有两个属性: 数据类型和数据的存储类别。 7.7 变量的存储类别 > < 静态变量:存储在静态存储区的变量。 在程序运行期间分配固定的存储空间不释放 生存期:从程序开始执行到程序结束 动态变量:存储在动态区的变量。 在程序运行期间根据需要临时分配存储空间,离开即释放 生存期:从包含该变量定义的函数开始执行至函数执行结束 存储类别:指 变量、函数等存储的方式和位置 存储器类型:寄存器、静态存储区、动态存储区 程序区 静态存储区 动态存储区 全局变量、局部静态变量 形参变量 局部动态变量(auto register) 函数调用现场保护和返回地址等 > < 变量的存储类型 auto -----自动型 register-----寄存器型 static ------静态型 extern -----外部型 变量定义格式: [存储类型] 数据类型 变量表; 如: int sum; auto int a,b,c; register int i; static float x,y; > < auto(自动)变量 没有声明为static的局部变量都属于此类。 如:函数中的形参和在函数中定义的变量(包括在复合语句中定义的变量)。 存储特性:存储在动态存储区。 调用时自动动态分配存储空间。调用结束后自动释放存储空间。 例如: int f(int a) /*定义f函数,a为形参 */ { auto int b,c=3;/*定义b、c为自动变量 */ … } 执行完f后,自动释放a、b、c所占的内存。 auto int b, c=3和int b, c=3等价。 > < register(寄存器)变量 只有auto变量与形式参数可以作为register变量 register变量和auto变量不同之处在于register变量存放在CPU的寄存器中,因此比auto变量存取速度快。通常将频繁使用的变量放在寄存器中,以提高程序执行速度 不能对寄存器变量使用取地址运算符& 计算机中寄存器的数量是有限的,而且寄存器的数据长度也是有限的。因此register变量不能定义太多,也不能是数据类型太大的变量(long、float、double型) 目前register变量定义通常是不必要的,优化的编译系统能够识别使用频繁的变量,并将其放到寄存器中 > < static(静态)变量 static变量存放在内存的静态存储区,在整个程序运行期间占用固定的内存单元。 可以修饰局部变量和全局变量。 系统在编译时为static变量分配空间并赋初值,对未赋值的局部static数值型变量,系统自动给它赋值为0;对未赋值的局部static字符型变量,自动赋值为空字符。因为在编译时赋初值,所以只能赋一次初值且只能在定义时进行。 由于变量占用的存储单元不消失,再次调用static局部变量时,static局部变量的值为上次调用结束时的值。 注意:static局部变量的生存期是整个程序运行期间,但作用域仍然是定义该变量的函数体(或复合语句)内部。 即:静态局部变量在函数调用结束后仍然存在,但其他函数不能引用它。 static修饰全局变量,将使全局变量作用域局限于本文件内。 > < main() { void increment(void); increment(); increment(); increment(); } void increment(void) { int x=0; x++; printf(“%d ”,x); } 练习 局部静态变量值具有可继承性 运行结果:1 1 1 main() { void increment(void); increment(); increment(); increment(); } void increment(void) { static int x=0; x++; printf(“%d ”,x); } 运行结果:1 2 3 > < #include <stdio.h> void main() { int f(int); int a=2,i; for (i=0;i<3;i++) printf(“%d”,f(a));   } int f(int a) { auto int b=0; int c=3; b=b+1;   c=c+1; return(a+b+c); } 考察静态局部变量的值。 #include <stdio.h> void main() { int f(int); int a=2,i; for (i=0;i<3;i++) printf(“%d”,f(a));   } int f(int a) { auto int b=0; static int c=3; b=b+1;   c=c+1; return(a+b+c); } 结果:7,8,9 b、c是自动变量,函数调用结束后, b、c的存储空间释放。 再一次调用, b、c重新赋值。 c是静态局部变量,在整个程序运行期间,c的空间都不释放,函数调用结束后后,c的值仍保留 再一次调用, c的值为保留的值。 结果:7,7,7 extern声明(外部)变量 全局变量都是存放在静态存储区中的。因此它们的生存期是固定的,存在于程序的整个运行过程。 全局变量是在函数的外部定义的,它的作用域是从变量的定义处开始,到本程序文件的末尾。 采用extern可以扩充全局变量的作用域。 外部变量定义与外部变量声明不同 > < 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对全局变量作用域的扩展 在多文件的程序中,引用其它文件中的外部变量需extern声明 例 int global; extern float x; main() { int local; . . . } extern int global; static int number; func2() { . . . } float x; static int number; func3() { extern int global; . . . } file1.c file2.c file3.c 用extern将外部变量的作用域扩展到其他文件。 > < 返回值 函数体 形参名 形参类型 函数名 返回值类型 int fac ( int num) { int i,t; for(i=1,t=1;i<=num;i++) t=t*i; return t; } 实参 b a 20 10 20 10 y x 形参 larger( ) { … 返回 } process( ) { … larger( ); … 返回 } main( ) { … process( ); … } 24 6 2 1 1 2 3 4 int factorial(int n) { if (n==1) return 1; else return (n*factorial(n-1)); } int factorial(int n) { if (n==1) return1; else return (n*factorial(n-1)); } int factorial(int n) { if (n==1) return1; else return (n*factorial(n-1)); } int factorial(int n) { if (n==1) return1; else return (n*factorial(n-1)); } { int n=4; long f; f=factorial(4); printf(“%d ”,f); }/*main function*/ $$

资源预览图

第7章 函数(课件)-《C语言程序设计(第四版)》同步教学(清华大学出版)
1
第7章 函数(课件)-《C语言程序设计(第四版)》同步教学(清华大学出版)
2
第7章 函数(课件)-《C语言程序设计(第四版)》同步教学(清华大学出版)
3
第7章 函数(课件)-《C语言程序设计(第四版)》同步教学(清华大学出版)
4
第7章 函数(课件)-《C语言程序设计(第四版)》同步教学(清华大学出版)
5
第7章 函数(课件)-《C语言程序设计(第四版)》同步教学(清华大学出版)
6
由于学科网是一个信息分享及获取的平台,不确保部分用户上传资料的 来源及知识产权归属。如您发现相关资料侵犯您的合法权益,请联系学科网,我们核实后将及时进行处理。