《C语言 第七章函数ppt课件.ppt》由会员分享,可在线阅读,更多相关《C语言 第七章函数ppt课件.ppt(58页珍藏版)》请在三一办公上搜索。
1、2022/11/16,1,第七章 函数,武汉理工大学计算机学院,2022/11/16,2,第七章 函数,7.1 函数的概念7.2 函数的定义7.3 函数的调用和函数的返回值7.4 函数应用实例7.5 嵌套调用和递归调用7.6 变量的作用域和存储类别7.7 内部函数和外部函数(*)7.8 编译预处理,2022/11/16,3,7.1函数的概念,#include stdio.hvoid stars(int n);void print_message( );main( ) stars(20); print_message( ); stars(20);void stars(int n) int i;
2、for (i=1; i=n; i+) putchar(*); putchar(n);void print_message( ) printf(How do you do!n);,函数stars( )、 print_message( )的声明,/*main函数的定义*/,stars( )、print_message( )函数调用,定义stars( )函数,定义print_message( )函数,程序运行后输出结果为:,2022/11/16,4,C 程序结构,2022/11/16,5,说明 :,C是函数式语言一个C程序有且只能有一个名为main的主函数。所有的函数都是互相独立的,除main函数不
3、能调用外,其它函数可以互相调用。函数库函数(标准函数)自定义函数,2022/11/16,6,7.2 函数的定义,类型说明符 函数名(形参说明表) 说明部分 语句部分,说明函数返回值的数据类型;若缺省,则为 int 类型;若函数无值,则定义为 void 类型。,由用户自己命名,合法的标识符,说明参数的个数和类型,说明函数中用到的除形参以外的其它变量等,为了完成函数特定的功能而设计的一个或多个语句,空函数 : Function( ) ,2022/11/16,7,函数定义实例,打印一行 n 个* void stars(int n) int i; for (i=1; i=n; i+) putchar(
4、*); putchar(n);,求整数x的n次幂(n0)long power(int x, int n) int i; long mul=1; for (i=1; i=n; i+) mul=mul*x; return(mul);,传统的定义风格,2022/11/16,8,传统的函数定义形式,long power(x, n)int x, n; int i; long mul=1; for (i=1; i=n; i+) mul=mul*x; return(mul);,2022/11/16,9,7.3 函数的调用和函数的返回值,7.3.1 函数的参数7.3.2 函数的返回值7.3.3 函数的声明7.
5、3.4 函数的调用,2022/11/16,10,7.3.1 函数的参数,形式参数:函数定义时所使用的参数称为形式参数。形参可以是:变量或数组名。实际参数:函数调用时所使用的参数称为实际参数。实参可以是:具有确切值的常量、变量、表达式或数组名。,2022/11/16,11,int max(int x, int y);void main( ) int a, b, c; scanf(%d%d, ,形参只能是变量或数组名,int max(int x, int y),c=max(a, b),实参可以是常量、变量、表达式或数组名,但要求它们有确定的值如: c=max(10, (a+b)/2);实参与形参之
6、间:个数一致,类型一致或赋值兼容,顺序一致。,形参:变量,值,2022/11/16,12,7.3.2 函数的返回值,返回语句(return语句):格式: return(表达式) ; 或 return 表达式; 或 return;功能:将流程及表达式的值从被调用函数返回到函数的调用处。说明:,int max(int x, int y) int z; z=(xy)?x:y; return(z);,若return后面带表达式,首先计算表达式的值,表达式的值就是所求的函数值。,return z ;,return(xy)?x:y);,2022/11/16,13,说明(续),一个函数体内可以有多个或没有r
7、eturn语句;,int max(int x, int y) int z; if(xy) return(x); else return(y);,void output(int m) printf(”%d”,m); return;,若return后面没有表达式,或没有return语句,则可能会返回不定值。,output(int m) printf(”%d”,m); return;,/*默认为int类型函数*/,void: 空类型,2022/11/16,14,7.3.3 函数的声明,#include stdio.hvoid stars(int n);void print_message( );ma
8、in( ) stars(20); print_message( ); stars(20);,void stars(int n) int i; for (i=1; i=n; i+) putchar(*); putchar(n);void print_message( ) printf(How do you do!n);,2022/11/16,15,函数声明的一般形式:函数类型 函数名( 类型名 形参1, 类型名 形参2,)包含参数和返回值类型的函数声明称为函数原型。函数类型 函数名(类型名, 类型名, )若有函数: float fun(double a, int b, float c) 则可有函
9、数声明: float fun(double a, int b, float c); float fun(double x, int y, float z); float fun(double, int, float);,说明:,2022/11/16,16,说明(续):,如果函数的值是 int 或 char 型,可以不必进行声明,系统自动按 int 型声明。,如果被调用函数出现在主调函数之前,可以不必进行声明。,#include main( ) int a, b, c; scanf(%d%d, ,int max(int x, int y) int z; z=xy?x:y; return(z);,
10、2022/11/16,17,说明(续):,如果已在所有函数定义之前,在函数的外部已作了函数声明,则在各个主调函数中不必对所调用的函数再做声明。,2022/11/16,18,7.3.4 函数的调用,调用的一般形式:函数名(实参1,实参2,)说明:若调用无参函数,则无实参表列,但括弧不能省略;如果实参表列包含多个实参,则各参数间用逗号隔开;实参与形参的个数应相等,类型应一致或赋值相容;实参与形参按顺序一一对应传递数据;,2022/11/16,19,调用方式函数语句:由函数调用加上分号构成,在主调函数中可作为一个独立的语句。如: stars(20); 或 printf(”C program”);函数
11、表达式:函数调用作为一个运算对象出现在表达式中,此时要求函数带回一个确定的值以参加表达式的运算。 如: c=mysqrt(a);函数参数:函数调用作为另一个函数的实参,其值作为一个实际参数传给被调函数的形参进行处理;此时也要求函数带回一个确定值。如: m=max(a, max(b, c); printf(%d, max(a, b) );,2022/11/16,20,调用过程float add( ); main( ) float a,b,c; scanf(”%f,%f ”,调用,流程从主调函数转移到被调用函数,且实参将值传给对应的形参;执行被调用函数;流程从被调用函数返回到主调函数,并返回函数值
12、。,6,15,6,15,21,2022/11/16,21,调用过程float add( ); main( ) float a,b,c; scanf(”%f,%f ”,6,15,10,17,17,27,11,18,29,29,形参:变量,实参:常量变量表达式,值,10,2022/11/16,22,7.4 函数应用实例,例7.1 求累加和 sum=1+2!+10!分析:可以编写一个求阶乘的函数fac(n)计算n!实现:,long fac(int n);main( ) int i; long sum=0; for(i=1;i=10;i+) sum+=fac(i); printf(”nsum=%ld”
13、,sum); ,long fac(int n) int i; long x=1L; for(i=1;i=n;i+) x*=i; return(x); ,2022/11/16,23,例7.2 由键盘输入x、y及z的值,计算函数 sin(x) sin(y) sin(z) func(x,y,z)= + + sin(x-y)sin(x-z) sin(y-z)sin(y-x) sin(z-x)sin(z-y),分析:可以定义一个函数part(x,y,z)求每加项的值另外定义一个度与弧度之间的转换函数change(x)主函数中以度为单位输入x、y及z的值,并转换为弧度;多次调用part( )函数求出fun
14、c的值输出func的值,2022/11/16,24,sin(x) sin(y) sin(z) func(x,y,z)= + + sin(x-y)sin(x-z) sin(y-z)sin(y-x) sin(z-x)sin(z-y),#includedouble change(float x);double part(float x,float y,float z);main() float x,y,z,sum; scanf(”%f%f%f”,2022/11/16,25,sin(x) sin(y) sin(z) func(x,y,z)= + + sin(x-y)sin(x-z) sin(y-z)s
15、in(y-x) sin(z-x)sin(z-y),double change(float x) return(x*3.14159/180);,double part(float x,float y,float z); float tmp; tmp=sin(x)/sin(x-y)/sin(x-z); return(tmp);,2022/11/16,26,7.5 函数的嵌套调用和递归调用,7.5.1 函数的嵌套调用7.5.2 函数的递归调用,2022/11/16,27,7.5.1 函数的嵌套调用,语言的函数定义都是互相平行的、独立的,即不允许嵌套定义函数;但是,可以嵌套调用函数,即程序在调用一个函
16、数的过程中,该被调函数又可以调用其它函数。如:,main函数,调用a函数,a函数,调用b函数,b函数,结束,2022/11/16,28,n m!例7.1 求组合数 C = m n! * (m-n)!,long cmn(int m, int n);long fac(int n);main( ) int m,n; long c; printf(”n输入两整数: ”); scanf(”%d%d”,long cmn(int m, int n) long x; x=fac(m)/fac(n)/fac(m-n); return(x); long fac(int n) long x=1L; while(n=
17、1) x*=n return(x); ,2022/11/16,29,调用过程,main函数,调用cmn函数,cmn(m,n),调用fac函数,fac(m),调用fac函数,fac(n),调用fac函数,fac(m-n),结束,2022/11/16,30,7.5.2 函数的递归调用,概念:定义一个函数时,在函数体内直接或间接地调用了自身,则称为函数的递归调用。,int f(int x) int y, z; z=f(y); return(z*z);,直接递归,间接递归,2022/11/16,31,递归的两个方面: 递归的一般形式 递归的结束条件,如: n!递推形式: n!=12n递归形式:,lon
18、g f(int n) long y; if (n=0) y=1; else y=f(n-1)*n; return(y);,main( ) int n; printf(ninput n(n0):); scanf(%d, ,运行过程演示,2022/11/16,32,main( ) n=5; print(f(5);,long f(5) long y; y=5*f(4); ,long f(4) long y; y=4*f(3); ,long f(3) long y; y=3*f(2); ,long f(3) long y; y=3*f(2); ,long f(2) long y; y=2*f(1);
19、,long f(1) long y; y=1*f(0); ,return(1);,return(2);,return(6);,return(6);,return(24);,return(120);,long f(0) long y; y=1;,return(1);,调用过程,2022/11/16,33,7.6 变量的作用域和存储类别,7.6.1 变量的作用域7.6.2 变量的存储类别7.6.3 小结,2022/11/16,34,7.6.1 变量的作用域,变量的作用域:是指在程序中不同位置所定义的变量,其变量起作用的区域。根据变量起作用的范围,变量可分为:局部变量:在函数内部或复合语句中定义的变
20、量,也称为内部变量。其作用域仅在所定义的函数或复合语句中。全局变量:在所有函数外部定义的变量,也称为外部变量。其作用域从定义位置开始到其所在 的源文件结束。,2022/11/16,35,1. 局部变量,main() int j,x, c; int c; c=j%2; ,int f1(int a) int v1, x; int f2( ) int v2, x, y; ,2022/11/16,36,例,void f( ) int a =1; printf(n1.a=%d, a );main( ) int a =10, i; f( ); for(i=1;i=2;i+) int a =50; a +;
21、 printf(n2.%d:a=%d, i, a ); printf(n3.a=%d, a );,程序运行结果为:,1,1,2,3,3,3,2,1.a=1,2.1:a=51,2.2:a=51,3.a=10,2022/11/16,37,程序运行结果为:1.a=12.1:a=512.2:a=513.a=10,51,1.a=12.1:a=512.2:a=513.a=10,2022/11/16,38,2. 全局变量,#include int p=1, q=5;main( ) int m,n; float f1(int a) int b, c; char c1, c2;char f2(int x, in
22、t y) int i, j; ., q 的作用范围,c1, c2的作用范围,2022/11/16,39,说明,全局变量增加了函数间的数据联系尽量少使用全局变量(除非在必要时),int k; void show( ) printf(n2.k=%d,k); k=9;main( ) k=2; show( ); printf(n1.k=%d,k);,运行结果:,2.k=21.k=9,2022/11/16,40,说明(续),若全局变量与局部变量同名,则在局部变量的作用范围内,全局变量不起作用,int a=3, b=5;int max(int a ,int b ) int c; c=a b ? a : b
23、; return(c);main( ) int a =10; printf(%d, max(a ,b) );,形参a、b的作用域全局变量a、b不起作用,局部变量a的作用域全局变量a不起作用,运行结果为:,10,2022/11/16,41,说明(续),可以用extern作外部变量声明,扩大全局变量的作用域,void f1( ) extern int c; extern int b; void f2( ) main( ) extern int a; int a=8,b=-2,c=15;,a b c,注意:extern int b=1; ,2022/11/16,42,7.6.2 变量的存储类别,存储
24、空间的划分,程序区:用于存放程序编译后形成的可执行代码(执行时装入)静态存储区:用于存放程序中的静态数据,如全局变量等动态存储区:用于存放程序中的动态数据,如函数形参、局部变量、函数调用时的现场保护和返回地址等,静态数据:说明时在静态存储区中分配存储单元并在程序执行过程中始终占用该单元,直到程序结束才释放;动态数据:在函数开始执行时分配动态存储空间,函数结束时释放这些空间。的存储类别有四种:auto、static、register和extern。,2022/11/16,43,局部变量的存储属性,自动的(auto)、静态的(static)、寄存器的(register)void f(int c);
25、main( ) register int i; /* i:局部寄存器变量*/ for (i=1; i=3; i+) f( i ); void f(int c) auto int a=0; /*a:局部自动变量,int a=0; */ static int b; /*b:局部静态变量,static int b=0;*/ a+; b+; printf(%d: a=%d, b=%dn, c, a, b);,存放在动态存储区,存放在静态存储区,存放在寄存器中,无地址,2022/11/16,44,寄存器变量说明,为了减少从内存中存取变量值的时间,语言允许将局部变量的值放在寄存器中;用关键字registe
26、r声明。 int fac(int n) register int i, f=1; for (i=1; i=n; i+) f=f * i; return( f );不能定义太多的寄存器变量,因为寄存器数量有限,太多无效(将自动按自动变量处理)寄存器无地址,因此: &i &f,返回,2022/11/16,45,自动变量和静态局部变量 区别,void f(int n) int a=0; static int b=0; a+; b+; printf(n%d: a=%d, b=%d, n, a, b);main( ) register int i; for (i=1; i=3; i+) f( i );,
27、1,1,1:a=1, b=1,2,2,2,3,3:a=1, b=3,2:a=1, b=2,0,1,3,0,1,3,4,程序结束,返回,2022/11/16,46,局部静态变量 说明,函数编译时在静态存储区分配存储单元,函数调用结束后不释放存储单元,即在整个程序的运行中不释放存储单元。用static声明该变量为“局部静态变量”若对变量赋初值,对于静态变量,只执行一次,再次调用函数时不再赋初值而保留上次函数调用结束时的值;而对于自动变量,每次调用都要重新分配内存单元并赋初值若不对变量赋初值,对于静态变量系统自动赋缺省值;而对于自动变量,只分配存储单元,其值不确定虽然静态局部变量在函数调用结束后仍占
28、存储单元,但由于是局部变量,其它函数不能引用它,2022/11/16,47,全局变量的存储方式,全局变量是在函数外部定义的,存放在静态存储区,在程序的整个运行过程中占用存储单元,生存期为整个程序的运行期间,2022/11/16,48,int c;void f(int n) int a=0; a+; c+; printf(n%d: a=%d, c=%d, n, a, c);main( ) int i; for (i=1; i=3; i+) f( i ); c+; printf(nc=%d,c);,1,1,1,1:a=1, c=1,2,2,2,0,1,3,2:a=1, c=3,4,3,3,0,1,
29、5,3:a=1, c=5,6,c=6,4,程序结束,2022/11/16,49,7.6.3 存储类别小结,1、数据的两种属性:,数据类型,存储类别,auto float a;,static int b;,register char c;,extern int d;,(声明变量是已定义的变量),2、从作用域分:,局部变量,全局变量,自动变量,静态局部变量,寄存器变量,形参,静态全局变量,非静态全局变量,2022/11/16,50,3、从生存期分:,动态存储,静态存储,自动变量,寄存器变量,形参,静态局部变量,静态全局变量,非静态全局变量,4、从存放位置分:,内存的静态存储区:,内存的动态存储区:
30、,CPU中的寄存器:,静态局部变量,静态全局变量,外部变量,自动变量,形参,寄存器变量,2022/11/16,51,7.7 内部函数和外部函数,2022/11/16,52,7.8 编译预处理,7.8.1 宏定义预处理命令7.8.2 文件包含预处理命令7.8.3 条件编译预处理命令,2022/11/16,53,7.8.1 宏定义预处理,宏定义分无参宏定义和有参宏定义;无参宏定义的一般格式 #define 标识符 字符序列 如: #define PI 3.1415926作用:用标识符(称为“宏名” PI )代替字符序列(3.1415926)。说明(1)宏名一般用大写字母表示,以示与变量区别。但这并
31、非是规定。(2)宏定义是用宏名代替字符序列,宏展开时仅作简单替换,不检查语法。语法检查在编译时进行。,2022/11/16,54,说明(续),(3)宏定义命令#define出现在函数的外部,宏名的有效范围是:从定义命令之后, 到本文件结束。通常,宏定义命令放在文件开头处。 (4) 在进行宏定义时,可以引用已定义的宏名 。如: #define M 10 #define N 2*M(5) 对双引号括起来的字符串内的字符,即使与宏名同名,也不进行宏展开。 如: #define M 10 printf(nM=%d,M);,2022/11/16,55,有参宏定义,2022/11/16,56,7.8.2 文件包含预处理,文件包含是指,一个源文件可以将另一个源文件的全部内容包含进来。文件包含处理命令的格式: include “包含文件名” 或 include ,2022/11/16,57,7.8.3 条件编译预处理,对部分内容指定编译的条件,称为“条件编译”。有以下几种条件编译命令:,#ifdef 标识符 程序段1#else 程序段2#endif,#ifndef 标识符 程序段1#else 程序段2#endif,#if 表达式 程序段1#else 程序段2#endif,2022/11/16,58,END,
链接地址:https://www.31ppt.com/p-1375701.html