《C语言-第七章--函数ppt课件.ppt》由会员分享,可在线阅读,更多相关《C语言-第七章--函数ppt课件.ppt(58页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、C语言程序设计2022-8-31第七章 函数武汉理工大学计算机学院2022-8-32第七章 函数7.1 函数的概念7.2 函数的定义7.3 函数的调用和函数的返回值7.4 函数应用实例7.5 嵌套调用和递归调用7.6 变量的作用域和存储类别7.7 内部函数和外部函数(*)7.8 编译预处理2022-8-337.1函数的概念#include stdio.hvoid stars(int n);void print_message( );main( ) stars(20); print_message( ); stars(20);void stars(int n) int i; for (i=1;
2、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-8-34C 程序结构源程序文件1预编译命令说明部分执行部分函数1函数n源程序文件i源程序文件nC程序2022-8-35说明 :C是函数式
3、语言一个C程序有且只能有一个名为main的主函数。所有的函数都是互相独立的,除main函数不能调用外,其它函数可以互相调用。函数库函数(标准函数)自定义函数有参函数无参函数或2022-8-367.2 函数的定义类型说明符类型说明符 函数名(函数名(形参说明表形参说明表) 说明部分说明部分 语句部分语句部分说明函数返回值的数据类型;若缺省,则为 int 类型;若函数无值,则定义为 void 类型。由用户自己命名,合法的标识符说明参数的个数和类型说明函数中用到的除形参以外的其它变量等为了完成函数特定的功能而设计的一个或多个语句 空函数 : Function( ) 2022-8-37函数定义实例打印
4、一行 n 个* void stars(int n) int i; for (i=1; i0)long power(int x, int n) int i; long mul=1; for (i=1; i=n; i+) mul=mul*x; return(mul);传统的定义风格2022-8-38传统的函数定义形式long power(x, n)int x, n; int i; long mul=1; for (i=1; iy?x:y; return(z);形参只能是变量或数组名int max(int x, int y)c=max(a, b)实参可以是常量、变量、表达式或数组名,但要求它们有确定
5、的值如: c=max(10, (a+b)/2);实参与形参之间:个数一致,类型一致或赋值兼容,顺序一致。形参:变量常量变量 实参表达式值值2022-8-3127.3.2 函数的返回值返回语句(return语句):格式: return(表达式) ; 或 return 表达式; 或 return;功能:将流程及表达式的值从被调用函数返回到函数的调用处。说明: max(int x, int y) int z; z=(xy)?x:y; return( );若return后面带表达式,首先计算表达式的值,表达式的值就是所求的函数值。return ;return(xy)?x:y);2022-8-313说明
6、(续)一个函数体内可以有多个或没有return语句; max(int x, int y) int z; if(xy) return(x); else return(y); output(int m) printf(”%d”,m); return; 若return后面没有表达式,或没有return语句,则可能会返回不定值。output(int m) printf(”%d”,m); return;/*默认为int类型函数*/2022-8-3147.3.3 函数的声明#include stdio.hvoid stars(int n);void print_message( );main( ) sta
7、rs(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-8-315函数声明的一般形式:函数类型 函数名( 类型名 形参1, 类型名 形参2,)包含参数和返回值类型的函数声明称为函数原型。函数类型 函数名(类型名, 类型名, )若有函数: float fun(double a, int b, float c) 则可有函数声明: float fun(
8、double a, int b, float c); float fun(double x, int y, float z); float fun(double, int, float);说明:2022-8-316说明(续):如果函数的值是 int 或 char 型,可以不必进行声明,系统自动按 int 型声明。如果被调用函数出现在主调函数之前,可以不必进行声明。#include main( ) int a, b, c; scanf(%d%d, &a, &b); c=max(a, b); printf(Max=%dn, c);int max(int x, int y) int z; z=xy?
9、x:y; return(z);2022-8-317说明(续):如果已在所有函数定义之前,在函数的外部已作了函数声明,则在各个主调函数中不必对所调用的函数再做声明。#include double mysqrt( float x);main( ) float a,c; scanf(”%f”, &a); c=mysqrt(a); printf(”sqrt(%f)=%fn”, a,c);double mysqrt(float x) double y; y=sqrt(x); return(y);2022-8-3187.3.4 函数的调用调用的一般形式:函数名(实参1,实参2,)说明:若调用无参函数,则无
10、实参表列,但括弧不能省略;如果实参表列包含多个实参,则各参数间用逗号隔开;实参与形参的个数应相等,类型应一致或赋值相容;实参与形参按顺序一一对应传递数据;2022-8-319调用方式函数语句:由函数调用加上分号构成,在主调函数中可作为一个独立的语句。如: stars(20); 或 printf(”C program”);函数表达式:函数调用作为一个运算对象出现在表达式中,此时要求函数带回一个确定的值以参加表达式的运算。 如: c=mysqrt(a);函数参数:函数调用作为另一个函数的实参,其值作为一个实际参数传给被调函数的形参进行处理;此时也要求函数带回一个确定值。如: m=max(a, ma
11、x(b, c); printf(%d, max(a, b) );2022-8-320调用过程float add( ); main( ) float a,b,c; scanf(”%f,%f ”,&a,&b); c=add(a,b); printf(”sum is %f ”,c);float add(float a, float b) return(a+b);1.调用,流程从主调函数转移到被调用函数,且实参将值传给对应的形参;2.执行被调用函数;3.流程从被调用函数返回到主调函数,并返回函数值。abc615a6b15212022-8-321调用过程float add( ); main( ) flo
12、at a,b,c; scanf(”%f,%f ”,&a,&b); c=add(10,b+2); printf(”sum is %f ”,c);float add(float a, float b) float c; c=a+b; a+; b+; return(a+b);abc615a10b1717c2711182929形参:变量实参:常量变量表达式值值102022-8-3227.4 函数应用实例例7.1 求累加和 sum=1+2!+10!分析:可以编写一个求阶乘的函数fac(n)计算n!实现: long fac(int n);main( ) int i; long sum=0; for(i=1
13、;i=10;i+) sum+=fac(i); printf(”nsum=%ld”,sum); long fac(int n) int i; long x=1L; for(i=1;i=n;i+) x*=i; return(x); 2022-8-323例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)主函数中以度为单位输入
14、x、y及z的值,并转换为弧度;多次调用part( )函数求出func的值输出func的值2022-8-324 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”,&x,&y,&z); x=change(x); y=change(y); z=change(z);
15、sum=part(x,y,z)+part(y,z,x)+part(z,x,y); printf(”nfunc=%f”,sum);2022-8-325 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)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);2
16、022-8-3267.5 函数的嵌套调用和递归调用7.5.1 函数的嵌套调用7.5.2 函数的递归调用2022-8-3277.5.1 函数的嵌套调用语言的函数定义都是互相平行的、独立的,即不允许嵌套定义函数;但是,可以嵌套调用函数,即程序在调用一个函数的过程中,该被调函数又可以调用其它函数。如:main函数调用a函数a函数调用b函数b函数结束main函数调用a函数a函数调用b函数b函数结束main函数调用a函数a函数调用b函数结束2022-8-328 n m!例7.1 求组合数 C = m n! * (m-n)!long cmn(int m, int n);long fac(int n);ma
17、in( ) int m,n; long c; printf(”n输入两整数: ”); scanf(”%d%d”,&m,&n); c=cmn(m,n); printf(”n组合数值=%ld”,c);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=1) x*=n return(x); 2022-8-329调用过程main函数调用cmn函数cmn(m,n)调用fac函数fac(m)调用fac函数fac(n)调用fac函数fac(m-n)结束ma
18、in函数调用cmn函数cmn(m,n)调用fac函数fac(m)调用fac函数fac(n)调用fac函数fac(m-n)结束2022-8-3307.5.2 函数的递归调用概念:定义一个函数时,在函数体内直接或间接地调用了自身,则称为函数的递归调用。int f1(int x) int y, z; z=f2(y); return(z);int f2(int t) int b, c; c=f1(c); return(3+c);int f(int x) int y, z; z=f(y); return(z*z);直接递归直接递归间接递归间接递归2022-8-331递归的两个方面: 递归的一般形式 递归
19、的结束条件如: n!递推形式: n!=12n递归形式:011)!1(!nnnnnlong 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, &n); if (n0) printf(Data error!n); else printf(%d! =%ldn, n, f(n);运行过程演示2022-8-332main( ) n=5; print(f(5);long f(5) long y; y=5*f(4); long f(4) long
20、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); 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-8-3337.6 变量的作用域和存储类别7.6.1 变量的作用域7.6.2 变量的存储类别7.6.3 小结2022-8-3347.6.1 变量
21、的作用域变量的作用域:是指在程序中不同位置所定义的变量,其变量起作用的区域。根据变量起作用的范围,变量可分为:局部变量:在函数内部或复合语句中定义的变量,也称为内部变量。其作用域仅在所定义的函数或复合语句中。全局变量:在所有函数外部定义的变量,也称为外部变量。其作用域从定义位置开始到其所在 的源文件结束。2022-8-3351. 局部变量main() int j,x, c; int c; c=j%2; int f1(int a) int v1, x; int f2( ) int v2, x, y; jxcca,v1,xv2,x,y2022-8-336例void f( ) int a =1; p
22、rintf(n1.a=%d, a );main( ) int a =10, i; f( ); for(i=1;i=2;i+) int a =50; a +; printf(n2.%d:a=%d, i, a ); printf(n3.a=%d, a );程序运行结果为:11233321.a=12.1:a=512.2:a=513.a=102022-8-337程序运行结果为:1.a=12.1:a=512.2:a=513.a=10a210511.a=12.1:a=512.2:a=513.a=10a210a350a3502022-8-3382. 全局变量#include int p=1, q=5;mai
23、n( ) int m,n; float f1(int a) int b, c; char c1, c2;char f2(int x, int y) int i, j; .p, q 的作用范围c1, c2的作用范围2022-8-339说明全局变量增加了函数间的数据联系尽量少使用全局变量(除非在必要时)int k; void show( ) printf(n2.k=%d,k); k=9;main( ) k=2; show( ); printf(n1.k=%d,k); 运行结果:2.k=21.k=92022-8-340说明(续)若全局变量与局部变量同名,则在局部变量的作用范围内,全局变量不起作用in
24、t a=3, b=5;int max(int a ,int b ) int c; c=a b ? a : b; return(c);main( ) int a =10; printf(%d, max(a ,b) );形参a、b的作用域全局变量a、b不起作用局部变量a的作用域全局变量a不起作用运行结果为:102022-8-341说明(续)可以用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
25、 int b=1; ac2022-8-3427.6.2 变量的存储类别存储空间的划分程序区程序区静态数据区静态数据区动态数据区动态数据区程序区:用于存放程序编译后形成的可执行代程序区:用于存放程序编译后形成的可执行代码(执行时装入)码(执行时装入)静态存储区:用于存放程序中的静态数据,如静态存储区:用于存放程序中的静态数据,如全局变量等全局变量等动态存储区:用于存放程序中的动态数据,如动态存储区:用于存放程序中的动态数据,如函数形参、局部变量、函数调用时的现函数形参、局部变量、函数调用时的现场保护和返回地址等场保护和返回地址等静态数据:静态数据:说明时在静态存储区中分配存储单元并在程序执说明时
26、在静态存储区中分配存储单元并在程序执行过程中始终占用该单元,直到程序结束才释放;行过程中始终占用该单元,直到程序结束才释放;动态数据:动态数据:在函数开始执行时分配动态存储空间,函数结束在函数开始执行时分配动态存储空间,函数结束时释放这些空间。时释放这些空间。的存储类别有四种:的存储类别有四种:auto、static、register和和extern。2022-8-343局部变量的存储属性自动的(auto)、静态的(static)、寄存器的(register)void f(int c);main( ) register int i; /* i:局部寄存器变量*/ for (i=1; i=3;
27、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-8-344寄存器变量说明为了减少从内存中存取变量值的时间,语言允许将局部变量的值放在寄存器中;用关键字register声明。 int fac(int n) register int i,
28、f=1; for (i=1; i=n; i+) f=f * i; return( f );不能定义太多的寄存器变量,因为寄存器数量有限,太多无效(将自动按自动变量处理)寄存器无地址,因此: &i &f返回返回2022-8-345自动变量和静态局部变量 区别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 );i1n1a0b011 1:a=1, b=1 22233:a=1, b=32:a=1,
29、 b=20 130 134程序结束程序结束返回返回2022-8-346局部静态变量 说明函数编译时在静态存储区分配存储单元,函数调用结束后不释放存储单元,即在整个程序的运行中不释放存储单元。用static声明该变量为“局部静态变量”若对变量赋初值,对于静态变量,只执行一次,再次调用函数时不再赋初值而保留上次函数调用结束时的值;而对于自动变量,每次调用都要重新分配内存单元并赋初值若不对变量赋初值,对于静态变量系统自动赋缺省值;而对于自动变量,只分配存储单元,其值不确定虽然静态局部变量在函数调用结束后仍占存储单元,但由于是局部变量,其它函数不能引用它2022-8-347全局变量的存储方式全局变量是
30、在函数外部定义的,存放在静态存储区,在程序的整个运行过程中占用存储单元,生存期为整个程序的运行期间2022-8-348int 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);c0i1n1a0 11 1:a=1, c=1 2220 132:a=1, c=34330 153:a=1, c=56c=64程序结束程序结束2022-8-3497.6.3 存储类别小结1、数据的两种属性:、数据的两种属
31、性:数据类型数据类型存储类别存储类别auto float a;static int b;register char c;extern int d;(声明变量是已定义的变量声明变量是已定义的变量)2、从作用域分:、从作用域分:局部变量局部变量全局变量全局变量自动变量自动变量静态局部变量静态局部变量寄存器变量寄存器变量形参形参静态全局变量静态全局变量非静态全局变量非静态全局变量2022-8-3503、从生存期分:、从生存期分:动态存储动态存储静态存储静态存储自动变量自动变量寄存器变量寄存器变量形参形参静态局部变量静态局部变量静态全局变量静态全局变量非静态全局变量非静态全局变量4、从存放位置分:、从
32、存放位置分:内存的静态存储区:内存的静态存储区:内存的动态存储区:内存的动态存储区:CPU中的寄存器:中的寄存器:静态局部变量静态局部变量静态全局变量静态全局变量外部变量外部变量自动变量自动变量形参形参寄存器变量寄存器变量2022-8-3517.7 内部函数和外部函数2022-8-3527.8 编译预处理7.8.1 宏定义预处理命令7.8.2 文件包含预处理命令7.8.3 条件编译预处理命令2022-8-3537.8.1 宏定义预处理宏定义分无参宏定义和有参宏定义;无参宏定义的一般格式 #define 标识符 字符序列 如: #define PI 3.1415926作用:用标识符(称为“宏名”
33、 PI )代替字符序列(3.1415926)。说明(1)宏名一般用大写字母表示,以示与变量区别。但这并非是规定。(2)宏定义是用宏名代替字符序列,宏展开时仅作简单替换,不检查语法。语法检查在编译时进行。2022-8-354说明(续)(3)宏定义命令#define出现在函数的外部,宏名的有效范围是:从定义命令之后, 到本文件结束。通常,宏定义命令放在文件开头处。 (4) 在进行宏定义时,可以引用已定义的宏名 。如: #define M 10 #define N 2*M(5) 对双引号括起来的字符串内的字符,即使与宏名同名,也不进行宏展开。 如: #define M 10 printf(nM=%d,M);2022-8-355有参宏定义2022-8-3567.8.2 文件包含预处理文件包含是指,一个源文件可以将另一个源文件的全部内容包含进来。文件包含处理命令的格式: include “包含文件名” 或 include 2022-8-3577.8.3 条件编译预处理对部分内容指定编译的条件,称为“条件编译”。有以下几种条件编译命令:#ifdef 标识符 程序段1#else 程序段2#endif#ifndef 标识符 程序段1#else 程序段2#endif#if 表达式 程序段1#else 程序段2#endif2022-8-358END
限制150内