C语言程序设计-第八章:函数_第1页
C语言程序设计-第八章:函数_第2页
C语言程序设计-第八章:函数_第3页
C语言程序设计-第八章:函数_第4页
C语言程序设计-第八章:函数_第5页
已阅读5页,还剩86页未读 继续免费阅读

下载本文档

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

文档简介

1、共 90 页 第 1 1 页 本章要点本章要点 函数的定义函数的定义 函数的调用函数的调用 函数间的数据传递函数间的数据传递 变量的存储类型变量的存储类型 变量的作用范围变量的作用范围 内部函数和外部函数内部函数和外部函数共 90 页 第 2 2 页 C C程序是函数的集合体,每程序是函数的集合体,每个函数是一个独立的程序模个函数是一个独立的程序模块块。 有一个主函数,若干个子函有一个主函数,若干个子函数,程序总是从主函数开始数,程序总是从主函数开始执行。执行。 函数可集中或分散存放在一函数可集中或分散存放在一个或多个源程序文件中。个或多个源程序文件中。 所有子函数地位平等,可互所有子函数地位

2、平等,可互相调用、自我调用。相调用、自我调用。 引入函数的优点:引入函数的优点: 减少重减少重复编写程序的工作量;使程复编写程序的工作量;使程序便于调试和阅读。序便于调试和阅读。函数函数F1 ( )main ( )F11 ( )F2 ( )F21 ( )F22 ( )共 90 页 第 3 3 页数学函数数学函数 math.h math.h字符和字符串函数字符和字符串函数 ctype.hctype.h, string.h, string.h输入输入/ /输出输出函数函数 stdio.hstdio.h动态存储分配函数动态存储分配函数 calloc(),malloccalloc(),malloc()

3、()形式形式无参无参函数函数有参有参函数函数空函数空函数库函数库函数用户定义函数用户定义函数: :共 90 页 第 4 4 页例例 输入三个整数,计算它们的和并输出运算结果。输入三个整数,计算它们的和并输出运算结果。int add(int x, int y, int z) int s; s=x+y+z; return s;函数示例定义的定义的求和函求和函数数main( ) int a, b, c, sum ; scanf(%d,%d,%d,&a,&b,&c); sum=add(a,b,c); printf( sum= %dn,sum); 调用求调用求和函数和函数共 90 页 第 5 5 页定义

4、函数应包括的内容:定义函数应包括的内容:(1)指定函数的名字,以便以后按名调用;)指定函数的名字,以便以后按名调用;(2)指定函数的类型,即函数值的类型;)指定函数的类型,即函数值的类型;(3)指定函数的参数的名字和类型(有参);)指定函数的参数的名字和类型(有参);(4)指定函数执行的操作,即函数完成的功能。)指定函数执行的操作,即函数完成的功能。在程序中用到的所有函数,必须先定义,后使用。在程序中用到的所有函数,必须先定义,后使用。共 90 页 第 6 6 页 定义函数的一般形式定义函数的一般形式类型标识符类型标识符 函数名函数名(形式参数表形式参数表) 说明部分说明部分 语句语句若无参数

5、,写若无参数,写void或空。或空。是被初始化的内部变量,是被初始化的内部变量,寿命和可见性仅限于函寿命和可见性仅限于函数内部数内部不说明类型,自动按整不说明类型,自动按整型处理型处理.建议都指定类型建议都指定类型函数体(一段程序,实现函数体(一段程序,实现函数的功能)函数的功能)共 90 页 第 7 7 页1. 无参函数的定义形式无参函数的定义形式 类型标识符类型标识符 函数名(函数名( ) 说明部分说明部分 语句语句 例例8-1 void print_message( ) printf(How are you !n); 共 90 页 第 8 8 页 例例8-2 int max (int x

6、,int y) int z; z=xy?x : y; return z; 类型标识符类型标识符 函数名(函数名(形式参数表列形式参数表列) 说明部分说明部分 语句语句 int max ( x, y) int x,y; int z; z=xy?x : y; return z; 形参变量的说明形参变量的说明(传统形式传统形式)形参变量的说明形参变量的说明(现代形式现代形式)2. 有参函数的定义形式有参函数的定义形式共 90 页 第 9 9 页3. 形式参数说明形式参数说明 形式参数形式参数: 在定义函数时函数名后面括弧中的变量名在定义函数时函数名后面括弧中的变量名在形参表中说明的形参,在函数体中不

7、再说明,可在形参表中说明的形参,在函数体中不再说明,可以同一般变量一样直接使用。以同一般变量一样直接使用。 形参形参调用前不占内存单元调用前不占内存单元,调用时分配内存单元。,调用时分配内存单元。调用结束后释放。调用结束后释放。形参是函数的内部变量,只在函数内部才有意义。形参是函数的内部变量,只在函数内部才有意义。对每个形参必须指明其名字和数据类型。对每个形参必须指明其名字和数据类型。多个形参用逗号分隔。多个形参用逗号分隔。共 90 页 第 1010 页例:有函数调用语句:例:有函数调用语句: int i=3; printf(”%d,%d”,i,+i);输出结果为:输出结果为:4,4 分析输出

8、函数的结果:分析输出函数的结果:自右向左:自右向左:4,4自左向右:自左向右:3,4避免这种不确定性:改为:避免这种不确定性:改为: int i=3, j; j=i; printf(”%d,%d”,i,+j);输出结果为:输出结果为:3,4共 90 页 第 1111 页 1. 函数调用的一般形式为:函数调用的一般形式为: 函数名(实际参数列表);函数名(实际参数列表); 或或 函数名(实际参数列表)函数名(实际参数列表)说明:说明: 实参必须有确定的值实参必须有确定的值,可以是常量、变量、表达式及函数调用。可以是常量、变量、表达式及函数调用。 实参与形参的类型、个数、顺序必须一致。实参与形参的

9、类型、个数、顺序必须一致。 多个实参用逗号分隔。多个实参用逗号分隔。 2. 执行过程:执行过程: 计算各个表达式(计算各个表达式(TC2.0,VC+6.0实参求值顺序按实参求值顺序按自右至左自右至左); 把得到值赋给对应的形参把得到值赋给对应的形参; 执行函数体执行函数体; 遇到遇到return语句或执行完最后一条语句语句或执行完最后一条语句,返回到函数调用处返回到函数调用处.共 90 页 第 1212 页(1) 函数语句函数语句: (把(把函数调用作为一个语句)函数调用作为一个语句) 一般形式:一般形式:函数名(实际参数表);函数名(实际参数表); 使用情况:这种方式常用于调用一个可以忽略返

10、回值使用情况:这种方式常用于调用一个可以忽略返回值或没有返回值的函数,只要求函数完成一定的操作。或没有返回值的函数,只要求函数完成一定的操作。 例如:例如: print_message( ); (2) 函数表达式:函数表达式:(函数调用出现在一个表达式中)(函数调用出现在一个表达式中) 一般形式:一般形式:变量名变量名= =函数表达式函数表达式 使用情况:这种表达式称为函数表达式。要求函数使用情况:这种表达式称为函数表达式。要求函数带回带回 一个确定的值参加表达式的运算。一个确定的值参加表达式的运算。 例如:例如:c=3+max(a, b); d=pow(c, i); e= f(x1,x2,x

11、3),(y1,y2); 函数有几个参数?函数有几个参数?共 90 页 第 1313 页 值传递值传递: 在函数调用时,实参将其在函数调用时,实参将其值值传递给形参。传递给形参。 实参对形参的数据传递是实参对形参的数据传递是“值传递值传递”,即单向传递,即单向传递,只,只由由实参实参传递给传递给形参形参,而不能由形参传回来给实参。,而不能由形参传回来给实参。 实参与形参占用不同的单元。在调用函数时,给形参分实参与形参占用不同的单元。在调用函数时,给形参分配存储单元,并将实参对应的值传递给形参,调用结束后,配存储单元,并将实参对应的值传递给形参,调用结束后,形参单元被释放,实参单元仍保留并维持原值

12、。在执行一个形参单元被释放,实参单元仍保留并维持原值。在执行一个被调用函数时,形参的值如果发生变化,并不会改变主调函被调用函数时,形参的值如果发生变化,并不会改变主调函数中实参的值。数中实参的值。8.1.4 函数参数的传递方式函数参数的传递方式 值传递的优点值传递的优点: :被调用的函数不可能改变调用函数中变量的值,被调用的函数不可能改变调用函数中变量的值,而只能改变它的局部的临时副本。而只能改变它的局部的临时副本。 值传递的缺点值传递的缺点: :每个形式参数仅能传递一个数据,不适用需每个形式参数仅能传递一个数据,不适用需要在函数之间传递大量数据。要在函数之间传递大量数据。 地址传递地址传递:

13、将实参的:将实参的地址地址传递给形参,实参和形参指向同一传递给形参,实参和形参指向同一内存空间,对形参的修改,可以直接影响实参。内存空间,对形参的修改,可以直接影响实参。共 90 页 第 1414 页例例8-3 编写函数交换两个变量的值。编写函数交换两个变量的值。 #include void swap ( int x, int y) int temp; temp=x; x=y; y=temp; printf ( x=%d, y=%dn, x, y); int main ( ) int a, b; a=5; b=10; printf ( a=%d, b=%dn, a, b); swap(a, b

14、); printf ( a=%d, b=%dn, a, b);运行结果:运行结果:a=5 ,b=10 x=10 ,y=5a=5 ,b=10共 90 页 第 1515 页 2. 2. 函数的返回值语句函数的返回值语句 一般形式:一般形式: return return 表达式表达式; ; 或或 return return (表达式);(表达式); 功能:功能:退出函数,将表达式的值带回主调函数,退出函数,将表达式的值带回主调函数,回到程序原来的位置继续执行。回到程序原来的位置继续执行。 return return 语句也可以没有表达式,其作用是使程语句也可以没有表达式,其作用是使程序执行的流程返回

15、到调用函数。序执行的流程返回到调用函数。 1. 定义定义:通过函数调用使主调函数得到一个确定:通过函数调用使主调函数得到一个确定 的值,称为的值,称为函数的返回值函数的返回值。共 90 页 第 1616 页说明:说明: returnreturn语句只能把语句只能把一个返回值一个返回值传递给调用函数。传递给调用函数。 返回值的类型为定义的函数类型,若返回值的类型为定义的函数类型,若returnreturn语句中语句中表达式类型与函数类型不一致,以表达式类型与函数类型不一致,以函数类型为准函数类型为准。 返回值可以是返回值可以是有确定值有确定值的常量、变量或表达式,也的常量、变量或表达式,也可以是

16、地址。当返值是地址时,应该用指针接受。可以是地址。当返值是地址时,应该用指针接受。 无返回值的函数,定义为无返回值的函数,定义为voidvoid类型类型( (无类型函数)。无类型函数)。 一个函数中可以有多个返回语句。一个函数中可以有多个返回语句。 exit()exit()函数由函数由ANSC CANSC C定义的,功能是终止和关闭所定义的,功能是终止和关闭所有程序,结束程序执行,忽略返回值。有程序,结束程序执行,忽略返回值。0 为正常退为正常退出出 非非0 为非正常退出。为非正常退出。共 90 页 第 1717 页 main( ) int a,b,c; scanf (“%d,%d”,&a,&

17、b); c=max(a,b); printf(“Max is %d”,c); 例8-4 int max(int x, int y) int z; z=xy? x:y; return(z); 形参:通知系统形参:通知系统 要预留内存位置要预留内存位置.实参:在运行时实参:在运行时把值传给函数把值传给函数.把函数的把函数的 结果赋给函数名结果赋给函数名形参与实参、函数名与返回值之间的关系形参与实参、函数名与返回值之间的关系共 90 页 第 1818 页double power(double x, int n) double p=1; int i; if(n0) for(i=1;i=n;i+) p=

18、p*x; return p;main()() int n; double x; scanf(“%d%lf”,&n,&x); printf(“%f”, power(x,n); 共 90 页 第 1919 页将一个给定的整数转换成字符串。将一个给定的整数转换成字符串。#include void to_str(int n) char string10; int i=0; if(n0) stringi+=n%10+0; n/=10; while(-i=0) putchar(stringi);int main() printf(The converted string: ); to_str(-123);

19、 return 0;运行结果:运行结果:The converted string:-123共 90 页 第 2020 页例例8-7 编写函数,求编写函数,求1+1/2+1/3+1/n的值,并在主函数中调用它。的值,并在主函数中调用它。#include double count(int n) int i; double sum=0; if(n=0) printf(Data error!n); return 0; else for(i=1;i=n;i+) sum+=1.0/i; return sum; int main() int n; double s; printf(Please input

20、the value: ); scanf(%d, &n); s=count(n); printf(s=%6.2lfn, s);运行结果:运行结果:Please input the value:5s= 2.28共 90 页 第 2121 页8.1.6 函数的声明函数的声明 问题的提出:问题的提出:C语言程序可由若干文件组成,每一个文件可语言程序可由若干文件组成,每一个文件可以单独编译。一个源程序文件由一个或多个函数组成。以单独编译。一个源程序文件由一个或多个函数组成。在一个函数中调用另一个函数需要具备如下条件:在一个函数中调用另一个函数需要具备如下条件:1)函数)函数必须是已经定义的函数;必须是已

21、经定义的函数;2)如果使用库函数,应该在文件)如果使用库函数,应该在文件开头包含库函数的信息;开头包含库函数的信息;3)若函数使用在定义之前,必须)若函数使用在定义之前,必须在调用函数前对函数进行声明。在调用函数前对函数进行声明。 同变量一样,函数的调用也应该遵循同变量一样,函数的调用也应该遵循“先说明,先说明,后使用后使用”的原则。的原则。 1. 函数声明的一般形式:函数声明的一般形式: 类型标识符类型标识符 函数名函数名( (类型类型1 1 形参形参1 1,类型,类型2 2 形参形参2,2,) ); ;功能:通知编译程序函数值类型、参数个数及类型,为编功能:通知编译程序函数值类型、参数个数

22、及类型,为编译程序进行类型检查提供依据。译程序进行类型检查提供依据。共 90 页 第 2222 页main() float add(float x,float y); float a, b, c; scanf(“ %f, %f”, &a, &b); c=add(a,b) ; printf(“ sum is %f ”, c );/*定义定义add函数函数*/float add (float x,float y) float z; z=x+y; return (z); 对被调用函数的说明作为表达式被调用共 90 页 第 2323 页2. 函数声明和函数定义的区别函数声明和函数定义的区别 函数声明函

23、数声明的作用是把函数的名字、函数类型以的作用是把函数的名字、函数类型以及形参的类型、个数和顺序通知编译系统,以便在及形参的类型、个数和顺序通知编译系统,以便在调用该函数时系统按此进行对照检查。调用该函数时系统按此进行对照检查。 函数定义函数定义是指对函数功能的确立,包括指定函是指对函数功能的确立,包括指定函数名、函数值类型、形参及其类型、函数体等,它数名、函数值类型、形参及其类型、函数体等,它是一个完整的、独立的函数单位。是一个完整的、独立的函数单位。 函数声明与函数定义的首部唯一区别:函数说明函数声明与函数定义的首部唯一区别:函数说明语句的(语句的( )之后必须)之后必须有分号有分号,而函数

24、定义头部的(,而函数定义头部的( )之后)之后没有分号没有分号。共 90 页 第 2424 页(1) 被调用函数在主调函数被调用函数在主调函数之前之前定义定义 float add (float x, float y) float z; z=x+y; return (z); main() float a, b; scanf(“ %f, %f, “&a, &b); printf(“ sum is %f ”, add(a, b) ); 3. 可省略被调用函数声明的二种情况可省略被调用函数声明的二种情况 共 90 页 第 2525 页(2) 在所有函数在所有函数定义之前说明定义之前说明char let

25、ter( char,char);float f(float,float );int i(float,float);main( ) .char letter (char c1,char c2)float f(float x,float y)int i(float,float)在所有函数之前在所有函数之前说明函数类型说明函数类型定义函数定义函数letter、f和和i共 90 页 第 2626 页8.2 数组作函数参数数组作函数参数数组元素可以作函数的实参数组元素可以作函数的实参 数组元素作为表达式的组成部分做函数的实参可数组元素作为表达式的组成部分做函数的实参可以单向将值传递给形参。以单向将值传递

26、给形参。 例如:例如: int a10; x=power( a6,5);数组名可以作函数的实参和形参数组名可以作函数的实参和形参 实现批量数据的传递实现批量数据的传递共 90 页 第 2727 页一维数组作函数参数,形参的写法为:一维数组作函数参数,形参的写法为: 类型说明符类型说明符 形参数组名形参数组名数组长度数组长度例如:例如: float average(float array10) main() float b10;int i; for(i=0;i10;i+) scanf(“%f”,&bi); average(b); 8.2.1 一维数组作函数参数一维数组作函数参数说明:说明:形参和

27、实参分别定义数组形参和实参分别定义数组数组做函数参数时,实参数组做函数参数时,实参用用数组名数组名, 必须有确切值必须有确切值实参数组和形参数组类型实参数组和形参数组类型应一致。应一致。共 90 页 第 2828 页说明:说明: 实参数组和形参数组大小不一定一致,实参数组和形参数组大小不一定一致,一维一维形参数组可形参数组可以不指定大小以不指定大小。 数组名除作为变量的标识外数组名除作为变量的标识外,还代表该还代表该数组在内存中存数组在内存中存放区域的首地址放区域的首地址。 数组名做函数实参与形参之间是数组名做函数实参与形参之间是“地址传递地址传递”,实参数实参数组将数组的起始地址传递给形参数

28、组。编译系统不再为组将数组的起始地址传递给形参数组。编译系统不再为形参数组分配存储单元。形参数组分配存储单元。 在函数体中对形参数组的元素操作时就是对实参数组的在函数体中对形参数组的元素操作时就是对实参数组的元素进行操作。元素进行操作。形参数组各元素的值发生变化会使实参形参数组各元素的值发生变化会使实参数组各元素的值发生同样的变化数组各元素的值发生同样的变化。 数组名作函数参数可实现大量数据的传递数组名作函数参数可实现大量数据的传递,无须返回数无须返回数组值。组值。共 90 页 第 2929 页例例8-8 阅读如下程序阅读如下程序,给出打印结果。给出打印结果。 void swap( int a

29、 ) int t; t=a0; a0=a1; a1=t; main( ) int b2=1,2 ; swap(b); printf(“b0=%d,b1=%dn”,b0,b1); 结果:结果:程序运行演示程序运行演示可不定义 长度b数组a数组在调用函数过程在调用函数过程中改变了原数组中改变了原数组的值,实参数组的值,实参数组与形参数组共享与形参数组共享一组存储空间,一组存储空间,共 90 页 第 3030 页例例8-9:编写函数用选择法对数组中编写函数用选择法对数组中10个整数由小到大排序个整数由小到大排序.程序设计思想程序设计思想:函数函数sort(array, n) :实现数组元素由小到大排

30、序。:实现数组元素由小到大排序。主程序主程序 :输入输入array数组,调用数组,调用 sort 函数比较,输函数比较,输 出排序后的出排序后的array数组。数组。void sort (int array , int n) int i, j, k, t; for (i=0; in-1; i+) k=i; for (j=i+1; jn; j+) if (arrayjarrayk) k=j; if (k!=i) t=arrayk; arrayk=arrayi; arrayi=t; 用另外一个参数表示用另外一个参数表示数组的长度数组的长度共 90 页 第 3131 页main ( ) int a1

31、0, i; printf(“enter array: n”); for (i=0; i10; i+) scanf (“ %d ”,&ai); sort(a, 10); printf(“the sorted array: n”); for (i=0; i10; i+) printf (“ %d ”, ai); printf(“n”);由于地址传递,由于地址传递,实参数组实参数组 a 改变改变数组名做参数的好处:数组名做参数的好处:由于只需复制一个地址值,而无须复制全部需要处由于只需复制一个地址值,而无须复制全部需要处 理的数据,因此节约存储空间并提高效率。理的数据,因此节约存储空间并提高效率。

32、由于主调函数和被调函数是在相同的内存区域上对由于主调函数和被调函数是在相同的内存区域上对 数据进行操作,因此可以实现数据的同步更新。数据进行操作,因此可以实现数据的同步更新。 函数调用共 90 页 第 3232 页例例8-10 将给定字符串复制到另一字符串将给定字符串复制到另一字符串。#include “stdio.h”void strcopy(char str1 ,char str2 ) int i=0; while(str1i!=0) str2i=str1i; i+; str2i=0;main() char s150,s250; printf(“Input string s1:”); ge

33、ts(s1); strcopy(s1,s2); printf(“%s”,s2);共 90 页 第 3333 页【例【例8-11】函数】函数del(s, i, n)的功能是从字符串的功能是从字符串s中删除从第中删除从第i个字符开始的个字符开始的n个字符。主函数调用个字符。主函数调用del函数,从字符串函数,从字符串management中删除从第中删除从第3个字个字符开始的符开始的4个字符,然后输出删除子串后的字符串。个字符,然后输出删除子串后的字符串。void del( char s , int i, int n) int j, k, length=0; while(slength!= 0) A

34、 ; j=-i; k=i+n; while(klength) sj+=sk+; sj= 0;main( ) char str=management; del( B ); printf(The new string is: %sn, str);答案答案 A: length+ B: str,3,4共 90 页 第 3434 页二维数组作函数参数,形参的写法为:二维数组作函数参数,形参的写法为: 类型说明符类型说明符 形参名形参名 数组长度数组长度1 数组长度数组长度2说明:说明: 形参数组定义时可以指定或形参数组定义时可以指定或省略第一维的大小省略第一维的大小 例如例如 : int array 3

35、10; 或或 int array 10; int array 3 ; 和和int array ;错误错误 实参数组可以实参数组可以大于大于形参数组形参数组 例如:实参数组定义为:例如:实参数组定义为:int array 510; 形参数组定义为:形参数组定义为:int array 310; 这时形参数组只取实参数组的一部分,其余部分不这时形参数组只取实参数组的一部分,其余部分不起作用。起作用。共 90 页 第 3535 页 例例8-12 8-12 编写函数,求编写函数,求3 3* *4 4矩阵中的最大值。矩阵中的最大值。 int max_value(int array 4) int i, j,

36、 max; max=array00; for(i=0 ; i3 ; i+) for(j=0; jmax) max=arrayij; return (max); int main() int a34=1,3,5,7,2,4,6,8,10,12,15,17; printf(“max=%dn”,max_value(a); 函数调用共 90 页 第 3636 页8.3 函数的嵌套调用和递归调用函数的嵌套调用和递归调用8.3.1 函数的嵌套调用函数的嵌套调用 嵌套定义:嵌套定义:在定义一个函数时,该函数体内包含在定义一个函数时,该函数体内包含另一个函数的定义。另一个函数的定义。 嵌套调用:嵌套调用:在调

37、用一个函数的过程中,又调用另在调用一个函数的过程中,又调用另一个函数。一个函数。 C语言不能嵌套定义,但可以嵌套调用!语言不能嵌套定义,但可以嵌套调用!共 90 页 第 3737 页main函数调用A函数结 束A函数调用B函数B函数192873456 两层嵌套的例子两层嵌套的例子共 90 页 第 3838 页 8.3.2 8.3.2 函数的递归调用函数的递归调用f 函数调用 f函数1. 1. 递归的概念:递归的概念: 在调用一个函数的过程中在调用一个函数的过程中直接直接或间接地调用该函数本身。或间接地调用该函数本身。直接调用:直接调用:intint f(x) f(x)intint x; x;

38、int int y,z; y,z; z=f(y); z=f(y); return (2 return (2* *z); z); 共 90 页 第 3939 页int f1(x)int x; int y,z; . z=f2( y); return (2*z); int f2(t)int t; int a,c; . c=f1(a); return (3+c); 间接调用:间接调用:f 1函数函数调用调用 f2函数函数f 2函数函数调用调用 f1函数函数共 90 页 第 4040 页递归函数的执行过程:递归函数的执行过程: -递归调用:记住本次现场,递归调用。递归调用:记住本次现场,递归调用。 -终

39、了调用:返回上次调用现场。终了调用:返回上次调用现场。特点:特点: -是无终止的递归调用,因此,是无终止的递归调用,因此,应该给定一应该给定一 个个限制递归次数的条件。限制递归次数的条件。 -结构简练。结构简练。共 90 页 第 4141 页float fac( int n) float f; if(n0) printf(“n1)例例8-13 用递归法求用递归法求n!调用阶乘函数不能赋给函数名共 90 页 第 4242 页递归函数递归函数facfac的求解过程,以求的求解过程,以求9 9的阶乘为例:的阶乘为例:fac(9)=9*fac( 8)fac(8)=8*fac( 7)fac(2)=2*f

40、ac( 1)fac(1)=1fac(9)=9*fac( 8)fac(8)=8*fac( 7)fac(2)=2*1fac(3)=3*fac( 2)fac(3)=3*2*1下下推推回回代代共 90 页 第 4343 页例例8-14 用递归法将一个整数用递归法将一个整数n转换成字符串。例如输入转换成字符串。例如输入256,应输出应输出“256”,n的位数不固定,可以是任意位数的整数。的位数不固定,可以是任意位数的整数。void void tranverstranvers(int(int n) n) if(n/10!=0) if(n/10!=0) tranvers(n/10);tranvers(n/1

41、0); printf(%c,n%10+0); printf(%c,n%10+0); main( )main( ) int int n; n; printf(“please printf(“please input an input an integral number”);integral number”); scanf(%d,&n scanf(%d,&n);); if(n if(n0)0) printf printf(“-);(“-); n=-1 n=-1* *n;n; tranvers(ntranvers(n);); 共 90 页 第 4444 页main()函数函数第一次调用第一次调用t

42、ranvers函数函数递归函数递归函数tranvers的求解过程示意图的求解过程示意图第二次调用第二次调用tranvers函数函数第三次调用第三次调用tranvers函数函数tranvers(25)输出字符输出字符2tranvers(2)输出字符输出字符5输出字符输出字符6tranvers(256)结束结束共 90 页 第 4545 页 char 型型 int 型型 float 型型 double 型型(VC+6.0环境)共 90 页 第 4646 页 变量的作用域和生存期变量的作用域和生存期: :u 变量的作用域变量的作用域 指一个变量在程序中的有效范围。(也称为可见性)指一个变量在程序中的

43、有效范围。(也称为可见性) C C语言规定语言规定:凡是在函数内定义的变量,它的作用域仅仅是凡是在函数内定义的变量,它的作用域仅仅是包含这个变量定义的复合语句包含这个变量定义的复合语句;而在函数体外定义的变量,而在函数体外定义的变量,它的作用域是它的作用域是从定义点到文件尾从定义点到文件尾。u 变量的生存期变量的生存期 指程序在执行期间,变量存在的时间间隔,即从给变量分指程序在执行期间,变量存在的时间间隔,即从给变量分配内存,至所分配内存被系统收回的那段时间。配内存,至所分配内存被系统收回的那段时间。 C C语言规定语言规定:凡是出现在静态数据区的变量,生存期都是从凡是出现在静态数据区的变量,

44、生存期都是从程序开始执行到程序结束;程序开始执行到程序结束;而出现在静态区之外的变量,生而出现在静态区之外的变量,生存期仅仅是从存期仅仅是从函数开始执行到函数执行结束函数开始执行到函数执行结束这段时间。这段时间。共 90 页 第 4747 页1.1.局部变量(内部变量)局部变量(内部变量) 定义:在函数内部定义的变量,只能在本函数内部使用。定义:在函数内部定义的变量,只能在本函数内部使用。 说明(避免了函数间的相互干扰,增加了函数的独立性)说明(避免了函数间的相互干扰,增加了函数的独立性) 主函数主函数 main main 定义的变量只在主函数中有效,定义的变量只在主函数中有效,主函数不能主函

45、数不能使用其它函数定义的变量使用其它函数定义的变量。 不同函数不同函数可以使用可以使用相同名字相同名字的变量。的变量。 形式参数也是局部变量。形式参数也是局部变量。 可以在一个函数内部,也可以在复合语句中定义变量,这可以在一个函数内部,也可以在复合语句中定义变量,这些变量只在些变量只在本复合语句中有效本复合语句中有效。8.4.1 局部变量和全局变量局部变量和全局变量char search(char s) char ch; int k; 变量变量s、ch、k的作用域的作用域编译系统不为局部变量分配内存编译系统不为局部变量分配内存单元,只是当被调用时,根据需单元,只是当被调用时,根据需要分配临时单

46、元,调用结束,空要分配临时单元,调用结束,空间释放。间释放。共 90 页 第 4848 页例:例:main()int m,n; int x,y;变量变量x,y的的作用域作用域变量变量m,n的的作用域作用域共 90 页 第 4949 页阅读以下程序,写出程序的运行结果。阅读以下程序,写出程序的运行结果。main() int i=3, j=2, k; k=i+j; int k=8; if(i=4) printf(%d, , k); else printf(%d, , j); printf(%d, %d,i,k); 2,3,5共 90 页 第 5050 页2. 2. 全局变量全局变量定义:定义:在函

47、数之外定义的变量是全局变量在函数之外定义的变量是全局变量( (外部变量外部变量) )。语法:语法:类型说明类型说明 变量名变量名 ;使用范围:使用范围:可以为本文件中所有的函数公用。可以为本文件中所有的函数公用。 从定义变量的位置开始到本文件结束,这段程序中的函数从定义变量的位置开始到本文件结束,这段程序中的函数可直接使用全局变量,可直接使用全局变量,int a,b=3;main( ) float k;char str(char s20) 全局变量全局变量a、b的作用域的作用域全局变量全局变量k的作用域的作用域共 90 页 第 5151 页 int p=1,q=5; /*外部变量外部变量*/

48、f1( int a) /*定义函数定义函数*/ int b,c; char c1,c2; /*外部变量外部变量*/ f2( int a, int b) /*定义函数定义函数*/ . main() int m,n 全局变量c1、c2的作用范围全局变量p、q的作用范围共 90 页 第 5252 页例如:例如:#include “stdio.h”int a=7,b=10;main( ) int a=5,c; c=a+b; printf(“c=%dn”,c); 在同一源文件中,全局变量和局部变量在同一源文件中,全局变量和局部变量可以同名可以同名,在局部变量的作用范围内,在局部变量的作用范围内,全局变量

49、不起作用。全局变量不起作用。C=15全局变量局布变量局部变量全局变量共 90 页 第 5353 页优点:优点: 函数间数据联系:同一文件中的一些函数引用全局函数间数据联系:同一文件中的一些函数引用全局 变量,当某个函数中改变了全局变量的值,其它函数变量,当某个函数中改变了全局变量的值,其它函数中的全局变量值也随之改变。中的全局变量值也随之改变。 函数可以得到多个返回值。函数可以得到多个返回值。(在所有函数之外说明的变在所有函数之外说明的变量是全局变量,它在所有函数中都是可见的。利用全局变量的量是全局变量,它在所有函数中都是可见的。利用全局变量的这个特性,可以在函数间传递数据。)这个特性,可以在

50、函数间传递数据。)缺点:缺点: 全局变量在程序的全部执行过程中都占用存储单元。全局变量在程序的全部执行过程中都占用存储单元。 降低函数的通用性。降低函数的通用性。 使用过多,降低程序的清晰性。使用过多,降低程序的清晰性。 全局变量应尽可能少用。全局变量应尽可能少用。 共 90 页 第 5454 页 例例8-15 编写函数,利用全局变量求一维数组中正数的平均值和编写函数,利用全局变量求一维数组中正数的平均值和负数的平均值传递给调用函数输出。负数的平均值传递给调用函数输出。#include float zaver=0,faver=0;void saver(int array ,int n) int

51、 i,z=0,f=0; for(i=0 ; i0) zaver+=arrayi;z+; if(arrayi0) faver+=arrayi;f+; if(z!=0) zaver=zaver/z; if(f!=0) faver=faver/f; main() int a10=1,-3,4,6,-2,7,9,-8,-5,0; saver(a,10); printf(“正数平均值正数平均值=%f,负数平均值负数平均值=%fn”,zaver,faver);共 90 页 第 5555 页下面程序的运行结果是(下面程序的运行结果是( )。)。#include “stdio.h”int x1=30,x2=4

52、0;void sub(int x,int y) x1=x;x=y;y=x1;main() int x3=10,x4=20; sub(x3,x4); sub(x2,x1); printf(“%d,%d,%d,%dn”,x3,x4,x1,x2);答案答案10,20,40,40 共 90 页 第 5656 页 变量的存储类别变量的存储类别 静态存储方式:静态存储方式:程序运行期间分配固定存储空间的方式。程序运行期间分配固定存储空间的方式。 动态存储方式:动态存储方式:程序运行期间根据需要进行动态的分配存储程序运行期间根据需要进行动态的分配存储空间的方式。空间的方式。程序区程序区静态存储区静态存储区动

53、态存储区动态存储区全局变量,局部静态变量全局变量,局部静态变量形式参数形式参数局部变量(自动)局部变量(自动)函数调用的现场函数调用的现场保护和返回地址保护和返回地址8.4.2 8.4.2 变量的存储方法变量的存储方法共 90 页 第 5757 页 动态存储变量特点动态存储变量特点 函数开始调用时为变量分配存储空间,函数结束时释放函数开始调用时为变量分配存储空间,函数结束时释放这些空间。一个程序两次调用同一函数,其中同一个局部变这些空间。一个程序两次调用同一函数,其中同一个局部变量的内存地址可能不同。量的内存地址可能不同。 静态存储变量特点静态存储变量特点 在在 静态存储区分配存储单元,整个程

54、序运行期间都不释放。静态存储区分配存储单元,整个程序运行期间都不释放。变量存贮类型有四种:变量存贮类型有四种:自动变量(自动变量(autoauto)静态变量(静态变量(staticstatic)外部变量(外部变量(externextern)寄存器变量(寄存器变量(registerregister)autoauto、staticstatic、externextern和和registerregister为存贮类型说明符。为存贮类型说明符。共 90 页 第 5858 页(1)自动变量)自动变量 (auto) 函数中的局部变量,不做任何存储类别的说明都为自动变量。函数中的局部变量,不做任何存储类别的说

55、明都为自动变量。 定义形式:定义形式:auto 类型说明符类型说明符 变量名变量名 ; 说明:说明:“auto”可以省略。可以省略。 以前所使用的全部变量都是自动变量。以前所使用的全部变量都是自动变量。 自动变量必须在一个自动变量必须在一个函数体的内部。函数体的内部。 函数的形参也是自动变量。函数的形参也是自动变量。 例如:例如:int b, c=3 等价于等价于 auto int b, c=3; 作用域作用域:包含变量定义的复合语句或所说明的函数内部:包含变量定义的复合语句或所说明的函数内部 ; 在函数被调用时才存在,从函数中返回时即消失,在函数被调用时才存在,从函数中返回时即消失, 值也仅

56、限于说明它的函数,在其它的函数中不能存取值也仅限于说明它的函数,在其它的函数中不能存取, 在两个不同的函数中可以分别使用同名的变量。在两个不同的函数中可以分别使用同名的变量。1.局部变量的存储方法局部变量的存储方法共 90 页 第 5959 页(2)局部静态变量)局部静态变量 定义形式:定义形式:在变量名前面加在变量名前面加 关键字关键字static static 类型说明符类型说明符 变量名;变量名;局部静态变量编译时赋初值,每次调用时不赋初值,局部静态变量编译时赋初值,每次调用时不赋初值,只保留调用结束时变量的值。如果不赋初值,编译只保留调用结束时变量的值。如果不赋初值,编译时自动赋时自动

57、赋0值。值。局部静态变量只允许所在函数引用,局部静态变量只允许所在函数引用,其它函数不能引用。其值整个程序运行期间都不释其它函数不能引用。其值整个程序运行期间都不释放。放。自动变量不赋初值,其值自动变量不赋初值,其值不确定不确定。每调用一次,重。每调用一次,重新赋值一次。新赋值一次。共 90 页 第 6060 页例如:例如:int f(int a) int b=0; static int c=3; b=b+1; c=c+1; return( a+b+c);main( ) int a=2 , i; for(i=0; i3; i+) printf(“%d,”,f(a);运行结果为:运行结果为: 7

58、 ,8 ,9第一次调第一次调用开始用开始第一次调第一次调用结束用结束第二次调第二次调用开始用开始0b34410c局部静态变量共 90 页 第 6161 页#include “stdio.h”int fun(int x, int y) static int m=0, i=2; i+=m+1; m=i+x+y; return m; main() int a=2,b=3; printf(%d, , fun(a,b); printf(%dn, fun(b,a); 8,17运行结果:共 90 页 第 6262 页(3)寄存器变量)寄存器变量 (register) 直接放置在运算器的寄存器中的变量称为寄存

59、器变量直接放置在运算器的寄存器中的变量称为寄存器变量. 定义形式:定义形式: register 类型说明符类型说明符 变量名;变量名; 作用:作用:对于使用频繁的变量,定义为寄存器变量,不必从内存对于使用频繁的变量,定义为寄存器变量,不必从内存而是直接从寄存器中取出参加运算,提高程序执行效率。而是直接从寄存器中取出参加运算,提高程序执行效率。 说明:说明:只有只有局部自动变量局部自动变量和和形式参数形式参数可作为寄存器变量,其它如局可作为寄存器变量,其它如局部静态变量和全局变量不可以。部静态变量和全局变量不可以。属于属于动态动态存储方式,函数开始调用时为变量分配寄存器空间,存储方式,函数开始调

60、用时为变量分配寄存器空间,函数结束时释放寄存器空间。函数结束时释放寄存器空间。只有只有int、char和指针类型可定义为寄存器变量,而和指针类型可定义为寄存器变量,而long、double和和float型变量不能设定为寄存器型型变量不能设定为寄存器型 。可用于变量空间分配的寄存器个数依赖于具体的机器。通常可用于变量空间分配的寄存器个数依赖于具体的机器。通常为为2到到3个,若在一个函数中说明多于个,若在一个函数中说明多于2到到3个寄存器变量,编个寄存器变量,编译程序会自动地将它们变为自动变量。译程序会自动地将它们变为自动变量。 共 90 页 第 6363 页2. 全局变量的存储类型(外部全局变量

温馨提示

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

评论

0/150

提交评论