第4章函数与C程序结构_第1页
第4章函数与C程序结构_第2页
第4章函数与C程序结构_第3页
第4章函数与C程序结构_第4页
第4章函数与C程序结构_第5页
已阅读5页,还剩140页未读 继续免费阅读

下载本文档

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

文档简介

1、C程序程序源文件源文件1源文件源文件i源文件源文件n函数函数1预处理语句预处理语句函数函数m说明说明/定义部分定义部分执行语句部分执行语句部分图图4.1 C程序的一般结构程序的一般结构返回值类型返回值类型 函数名函数名(形式参数列表形式参数列表) 函数体函数体return; 程序实现了计算从键盘程序实现了计算从键盘输入一个整数输入一个整数n n,并求,并求其阶乘的功能。如果在其阶乘的功能。如果在今后的应用中,需要将今后的应用中,需要将求某数阶乘的功能作为求某数阶乘的功能作为程序中相对独立的一个程序中相对独立的一个部分(功能)部分(功能), ,则需要则需要将上述功能用自编函数将上述功能用自编函数

2、的方式实现的方式实现 long为函数返回值类型Return语句将语句将n!返回给!返回给调用函数调用函数花括号给函数确定了边界区域 long factorial( )inti,n;long fact=1;printf(Input n:); scanf(%d,&n);for(i=1;iy?x:y; /*函数体的执行部分函数体的执行部分 */ return temp; /*返回函数值返回函数值 */ 函数返回类型函数返回类型函数名函数名 形式参数形式参数函数声明告诉编译系统函数声明告诉编译系统factorial是一个返回值是是一个返回值是long,只有一个,只有一个int参数的函参数的函数

3、,注意最后分号不可少!数,注意最后分号不可少!程序演示形式参数形式参数(简称形参简称形参)实际参数实际参数(简简称实参称实参)程序演示 什么是函数的调用?先看下列程序什么是函数的调用?先看下列程序/*计算计算 S=2!-3!+4!*/ #include void main( ) float qsn(int x); /函数的声明函数的声明 float s; s=qsn(2)-qsn(3)+qsn(4); /*直接调用直接调用qsn函数进行计算函数进行计算*/ printf(“S=%fn”,s); float qsn ( int n) /*定义函数qsn为阶乘*/ int k; float qsn

4、; qsn=1; for (k=1;k=n;k+) qsn*=k; return (qsn); 程序演示A19233.141596.02e+23101105地址地址内存空间内存空间10010110510911720502046char型,占型,占1字节字节b int 型,占型,占4字节字节c float 型,占型,占4字节字节d double 型,占型,占8字节字节pq2046存放的是整数存放的是整数1923的地址的地址p,2050存放的是浮点数存放的是浮点数3.14159的的地址地址q,这就需要我们用一种新的数据表示存储的数据是地址而,这就需要我们用一种新的数据表示存储的数据是地址而不是其他

5、的数值。不是其他的数值。int x;int *p; /*变量前加*,表示该变量是指针变量*/p=&x; 101指针指针p地址地址101变量变量x(a) 将将x的地址装入的地址装入p(b) 指针指针p指向变量指向变量x指针指针p地址地址101变量变量xp=&x称称*p为指针为指针p的目标变量,也就是变量的目标变量,也就是变量x,指针除了可以指向,指针除了可以指向变量外,还可以指向内存中其它任何一种数据结构,如数组、变量外,还可以指向内存中其它任何一种数据结构,如数组、结构体类型和函数等。结构体类型和函数等。类型标识符类型标识符 *指针名指针名 2500025000 100 xy

6、10025000 xya)b)图图4.3 指针变量指针变量y与变量与变量x的存储关系图的存储关系图 x=8;或或*y=8; &x或或 &(*y)怎样用指针运算符来处理数据呢?怎样用指针运算符来处理数据呢? 设变量设变量x、y同类型,把同类型,把x复制到复制到y中,可采取下列方法:中,可采取下列方法:直接赋值:直接赋值: y=x;使用指针:设指针变量使用指针:设指针变量p用于保存用于保存x的地址:的地址: p=&x; 再执行语句再执行语句 y=*p;例如下列程序段例如下列程序段 int x=20,y,*ptr;ptr=&x;y=*ptr;该程序段的意思为:定义整型

7、变量该程序段的意思为:定义整型变量x(初值为初值为20),y和指针和指针*ptr,将将变量变量x的地址赋给指针变量的地址赋给指针变量ptr,然后以指针变量然后以指针变量ptr的值为内存的值为内存单元地址,将该单元的数据取出赋给变量单元地址,将该单元的数据取出赋给变量y,相当于语句相当于语句y=x;程序演示以以16进制形式进制形式输出无符号整数输出无符号整数3510002000 xyabta) 参数传递过程参数传递过程中中3510002000 xyabtb) 参数传递完成后参数传递完成后35100020003xyabtc) t=t=* *x执行执行后后55100020003xyabtd) *x=

8、*y执行后执行后53100020003xyabte) *y=ty=t执行后执行后图图4.4 地址值传递函数调用时参数的变化情况地址值传递函数调用时参数的变化情况程序演示3510002000 xyabta) 参数传递过程中参数传递过程中3510002000 xyabtb) 参数传递完成后参数传递完成后35100020001000 xyabtc) t=t=x执行执行后后35200020001000 xyabtd) x=y执行后执行后35200010001000 xyabte) y=ty=t执行后执行后图图4.5地址值传递函数调用时参数的变化情况地址值传递函数调用时参数的变化情况程序演示程序演示pt

9、rarrayarray0*ptrarrayiarray1array2array3*(ptr+1)*(ptr+2)*(ptr+3)*(ptr+i)如图:数组与指针的关系,当数组名传如图:数组与指针的关系,当数组名传给函数时,传送的是数组的起始位置给函数时,传送的是数组的起始位置实参数组实参数组a形参数组形参数组b注:形参数组注:形参数组b本质上是指针变量本质上是指针变量图图4.6 数组存储区域数组存储区域全部共享时全部共享时形参数组与实参数组的关形参数组与实参数组的关系系实参数组实参数组&a2形参数组形参数组b 注:形参数组注:形参数组b本质上是指针变量本质上是指针变量图图4.7 数组存

10、储区域数组存储区域部分共享部分共享时形参数组与实参数组的关系时形参数组与实参数组的关系程序演示/* Name:ex04-09.cpp */#include #define N 10void main()int sum(int v,int n); int aN=1,2,3,4,5,6,7,8,9,10,total,pos; printf(请输入求和起始元素序号请输入求和起始元素序号: ); scanf(%d,&pos); total=sum(&apos,N-pos);printf(total=%ldn,total);int sum(int v,int n)int i,s=0;fo

11、r(i=0;in;i+)s+=vi;return s;程序演示 数组数组a的起始的起始地址地址数组的起始地数组的起始地址表示方法址表示方法a 表示平面的起始地址表示平面的起始地址(二级地址)(二级地址)&a00 表示线性的起始地址(一级地址)表示线性的起始地址(一级地址)a0 表示线性的起始地址(一级地址)表示线性的起始地址(一级地址)*a 表示线性的起始地址(一级地址)表示线性的起始地址(一级地址)图图4.8 二维数组起始地址的表示方法示意二维数组起始地址的表示方法示意 二维数组在存储时也是有序地占用一片连续的内存区二维数组在存储时也是有序地占用一片连续的内存区域,数组的名字表示这段

12、存储区域的首地址。需要特别注域,数组的名字表示这段存储区域的首地址。需要特别注意的是,二维数组起始地址有多种表示方法,而且这些表意的是,二维数组起始地址有多种表示方法,而且这些表示方法在物理含义上还有表示平面起始地址和表示线性起示方法在物理含义上还有表示平面起始地址和表示线性起始地址之分,所以在使用二维数组的起始地址使必须注意始地址之分,所以在使用二维数组的起始地址使必须注意区分需要用哪一种起始地址。区分需要用哪一种起始地址。 实参用实参用a形参用形参用b5图图4.9 实际参数为二维数组名字实际参数为二维数组名字程序演示int max(int vN)int max(int vN)/注意数注意数

13、组参数只能省略最高维的长度指定组参数只能省略最高维的长度指定 int i,j,maxv;int i,j,maxv;maxv=v00;maxv=v00;for(i=0;iM;i+)for(i=0;iM;i+)for(j=0;jN;j+)for(j=0;jmaxv)if(vijmaxv)maxv=vij;maxv=vij;return maxv;return maxv; 程序演示实参数组实参数组a形参数组形参数组b注:形参数组注:形参数组b本质上是指针变量本质上是指针变量图图4.6 数组存储区域全部共享时形参数组与实参数组的关系数组存储区域全部共享时形参数组与实参数组的关系int max(int

14、v,int m,int n)int max(int v,int m,int n) int i,j,maxv;int i,j,maxv;maxv=v0;maxv=v0;for(i=0;im;i+)for(i=0;im;i+)for(j=0;jn;j+)for(j=0;jmaxv)n+jmaxv)maxv=vimaxv=vi* *n+j;n+j;return maxv;return maxv; 程序演示主函数主函数函数函数fun1函数函数fun2程序运行结束程序运行结束调用函数调用函数fun1调用函数调用函数fun2fun1执行结束执行结束fun2执行结束执行结束图图4.10 4.10 两层函数嵌

15、套调用示意图两层函数嵌套调用示意图kkkns.21void main()void main() int n,k; int n,k; scanf(“%d,%d”,&n,&k);scanf(“%d,%d”,&n,&k); printf(Sum of printf(Sum of %d%d powers of powers of integers from 1 to integers from 1 to %d%d = , = ,k k, ,n n);); printf(%dn, printf(%dn,f2(n,k)f2(n,k);); 输入:输入:4 4,5 5结果:结

16、果:Sum of 5 powers of integers Sum of 5 powers of integers from 1 to 4= 1300from 1 to 4= 1300该程序中,该程序中,main()main()中调用了中调用了f2()f2()函数,而函数,而f2()f2()函数中又调用了函数中又调用了f1()f1()函数,这就是函函数,这就是函数的嵌套调用。数的嵌套调用。程序演示执行如下图topa) 空栈空栈topputchar(a)topc) putchar(a)putchar(b)topd) putchar(a)putchar(b)putchar(c)tope) putc

17、har(a)putchar(b)topputchar(a)b) f) topg) 空栈空栈图图4.11 递归调用时系统堆栈数据的变化示意图递归调用时系统堆栈数据的变化示意图程序演示执行如下:执行如下:程序演示fac(4) *5fac(3)*4*5fac(2)*3*4*5fac(1)*2*3*4*5调用调用返回fac(5)fac(5) fac(4)*5fac(4) fac(3)*4fac(3) fac(2)*3fac(2) fac(1)*2fac(1) 1递归压栈方向递归压栈方向fac(2) fac(1) *21*2 2fac(3) fac(2) *32*3 6fac(4) fac(3) *46

18、*4 24fac(5) fac(4) *524*5 120递归回溯方向递归回溯方向图图4.12 函数递归调用过程示意图函数递归调用过程示意图执行如下:执行如下:程序演示1) 2() 1(101)(nnfnfnnfn=0或者或者n=1fib(n)retuan 1return fib(n-1)+fib(n-2)TF图图4.13 菲波拉契数列的递归算法菲波拉契数列的递归算法程序演示0)%(),(0)%(),(nmrrnGcdnmrnnmGcdr=m%n=0gcd(n)retuan nreturn gcd(n,r)TF图图4.14 最大公约数的递归算法最大公约数的递归算法int Gcd(int m,i

19、nt n)int r;if(r=m%n)=0)return n;elsereturn Gcd(n,r);程序演示void hanoi(int n,char a,char b,char c)if(n=1)printf(nMove disc %d from pile %c to %c,n,a,b);elsehanoi(n-1,a,c,b);printf(nMove disc %d from pile %c to %c,n,a,b);hanoi(n-1,c,b,a);程序演示 程序在第程序在第5 5行定义行定义了整型变量,由于变了整型变量,由于变量量x x定义在所有函数的定义在所有函数的外面,所以变

20、量外面,所以变量x x是全是全局变量,其作用范围局变量,其作用范围(作用域)从第(作用域)从第5 5行开行开始至第始至第1919行结束。同行结束。同时由于在定义全局变时由于在定义全局变量量x x时没有对其显式初时没有对其显式初始化。该程序运行的始化。该程序运行的结果为:结果为:x=4x=4。 程序演示 全局变量全局变量X的作用范围的作用范围 c1c1、c2c2、a a、b b、虽然虽然 都是全局变量,都是全局变量,但作用的范围不一但作用的范围不一样。样。c1c1、c2c2在开始在开始定义,所以在定义,所以在f1()f1(),f2()f2(),主函数内都,主函数内都有效,而有效,而a a、仅仅在

21、、仅仅在f2()f2(),主函数内都,主函数内都有效。有效。 在主函数中又定在主函数中又定义了义了2 2个局部变量个局部变量a a、b b。这时全局变量不。这时全局变量不起作用。起作用。即当全局即当全局变量和局部变量同变量和局部变量同名时,在局部变量名时,在局部变量作用范围内,全局作用范围内,全局变量不起作用变量不起作用。全局全局变量变量ab的的作用作用范围范围全全局局变变量量c1c2的的作作用用范范围围输出结果:输出结果:max(8,5)=8max(8,5)=8 思考:思考:主函数中如果没有主函数中如果没有int int x=8,x=8,结果是多少?结果是多少?如果全局变量如果全局变量x=-

22、3,x=-3,结结果又是多少?果又是多少?如果要将全局变量作如果要将全局变量作用域扩展到其他源文用域扩展到其他源文件,在变量定义前加件,在变量定义前加extermexterm。例如。例如exterm int x=3,y=5; exterm int x=3,y=5; 函数函数increincre在第一次被调用在第一次被调用时,会创建局部变量时,会创建局部变量x x并赋初值并赋初值为为2020,然后对其进行加,然后对其进行加5 5的操作的操作并将结果并将结果2525返回到主函数中输返回到主函数中输出(注意:随着出(注意:随着函数执行完成函数执行完成后后控制流程的返回,函数中定控制流程的返回,函数中

23、定义的局部变量(自动变量)义的局部变量(自动变量)x x被被系统自动撤销)。当函数系统自动撤销)。当函数increincre第二次被调用时,会重新创建第二次被调用时,会重新创建局部变量局部变量x x并赋初值为并赋初值为2020,然后然后对其进行加对其进行加5 5的操作并将结果的操作并将结果2525返回到主函数中输出,所以程返回到主函数中输出,所以程序执行的结果为:序执行的结果为:x=25x=25x=25x=25 函数的每次调用都是使用不同局部变量组。函数的每次调用都是使用不同局部变量组。程序演示*图图4.15 字符图形字符图形/* Name: ex04-20.cpp */#include vo

24、id main()void myprint();int i;for(i=0;i5;i+)myprint();void myprint()int i;for(i=0;i15;i+) putchar(*);printf(n);程序演示局部局部变量变量i的作的作用范用范围围局部局部变量变量i的作的作用范用范围围.main() float a,b; float c; c=a*b; 局部变局部变量量C的的作用范作用范围围局部局部变量变量a、b的作的作用范用范围围int x;void main()x+;void f1() int x=1; int x=2; x+; x+;void f2() x+;全局变量全局变量x的作的作用域用域图图4.16 全局变量与局部变量作用域重叠示意图全局变量与局部变量作用域重叠示意图复合语句内部定义的复合语句内部定义的局部变量局部变量x的作用域的作用域函数内部定义的局函数内部定义的局部变量部变量x的作用域的作用域程序演示x原作用域原作用域X的的作作用用域域被被扩扩充充例4-22程序执行的结果为:主函数中的输出:110 函数f中的输出:130程序演示程序演示double circum()return 2.0*3.1415926*2.0;double area()return

温馨提示

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

评论

0/150

提交评论