语言-课件2第七章_第1页
语言-课件2第七章_第2页
语言-课件2第七章_第3页
语言-课件2第七章_第4页
语言-课件2第七章_第5页
已阅读5页,还剩85页未读 继续免费阅读

下载本文档

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

文档简介

81页第1

页第七章函数共

81页第2

本章要点函数的定义函数的调用函数参数的传递方式变量的作用域和存储方法内部函数和外部函数共

81页第3

页C程序是函数的集合体,每个函数是一个独立的程序模块;由一个主函数和若干个子函数组成,程序总是从主函数开始执行;所有子函数地位平等,可互相调用、自我调用。函数可集中或分散存放在一个或多个源程序文件中。·

引入函数的优点:减少重复编写程序的工作量;使程序便于调试和阅读。

函数F1()main()F11()F2()F21()F22()C语言程序的结构7.1函数的概念和函数的定义共

81页第4

页main:主函数e,d,h,g被多次调用a,b,c,d,e,f,g,h,相互调用mainabdeghhgedcgf函数是C程序的最小单元。主函数可以调用其它函数,其它函数可以相互调用.函数调用举例main()

/*主函数*/{

printstar();

/*调用printstar函数画****/

print_message();

/*调用print_message函数写字*/

printstar();

/*调用printstar函数画****/}

printstar()

/*printstar函数*/{printf(“\n**********”);}print_message()

/*print_message函数*/

{printf(“\nHello!”);}运行结果:**********

Hello!**********

一个c程序由一个或多个源文件组成#include“lx2.c”#include“lx3.c”main()

{

printstar();

print_message();

printstar();}

printstar()

{printf(“\n**********”);}print_message(){printf(“\nHello!”);}Lx1.cLx2.cLx3.c共

81页第7

页数学函数

#includemath.h字符和字符串函数

ctype.h,string.hI/O函数#includestdio.h动态存储分配函数

形式有参函数无参函数空函数库函数用户定义函数:C函数的分类共

81页第8

页一、定义形式:[类型标识符]函数名([形式参数表])[形式参数说明]{[说明与定义部分]

语句}7.1.2函数的定义各形参之间用”,”隔开形参可以缺省,但括号不可省若该项缺省,自动按整型处理。函数体(是一段程序,实现函数的功能)函数名字有值,它代表函数的入口地址。有参函数定义形式有参函数定义形式共

81页第9

页无参函数的定义形式:

[类型标识符]

函数名()

{[说明部分]

语句

}

例:print_message(){printf(“Howareyou!\n”);}例:dummy

()

{}

没有数据类型说明、和形参说明函数体为空。无参函数定义空函数定义共

81页第10

long

facto

(

n

)

int

n;

{longs=1;inti;for(i=1;i<=n;i++)s*=i;return(s);

}函数名形式参数列表函数类型形式参数说明函数体函数返回

求阶乘函数facto的定义函数的定义(举例)共

81页第11

main(){

inta,b,c;intmax();scanf(”%d,%d”,&a,&b);

c=

max(a,b);

printf(”Max=%d”,c);}int

max

(

x,

y

)

intx,y;{

intz;z=x>y?x:y;return(z);}形式参数列表:是用“,”分开的一组变量,用来接收调用时传入的数据形式参数说明:在{外面对形式参数的类型进行说明函数调用求两个变量的最大值函数的定义(举例)函数声明共

81页第12

页二、形式参数和实际参数形式参数:形参调用前不占内存单元,调用时占用,调用后释放形参是函数的内部变量,只在函数内部才有意义。对每个形参必须指明其名字和数据类型。实际参数:实参必须有确定的值,可以是常量,变量或表达式。实参与形参的类型、个数必须一致。共

81页第13

页7.1.3函数的调用1.函数调用的一般形式为:

函数名(实际参数列表);或函数名(实际参数列表)实参的数量、类型和排列顺序必须与函数定义时形参表中形参的数量、类型和排列顺序一致。

2.

执行过程:在一个函数中调用另一个函数时,程序将控制从调用函数处转移到被调用函数,并且执行被调用函数。在执行完被调用函数的所有语句或者遇到return语句时,程序的控制要返回到调用函数中原来调用函数的地方继续执行。共

81页第14

页例:调用max函数的程序main(){inta,b,c;intmax();scanf("%d,%d",&a,&b);

c=max(a,b);printf("max=%d\n",c);}

函数调用intmax(x,y)intx,y;{intz;if(x>y)z=x;elsez=y;return(z);}实际参数形式参数返回函数值接收返回值程序执行顺序?共

81页第15

页/*1*//*2*//*3*//*4*//*5*//*11*//*12*//*13*//*14*//*15*//*16*/main(){inta,b,c;intmax();scanf("%d,%d",&a,&b);c=max(a,b);printf("max=%d\n",c);}intmax(x,y)intx,y;{intz;if(x>y)z=x;elsez=y;return(z);}断点保护断点和现场,转向11入口返回断点恢复现场带回函数值函数执行过程虚实结合ax,by共

81页第16

页(1)函数语句

(把函数调用作为一个语句)

一般形式:函数名(实际参数表);

此时不要求函数带回值,只要求函数完成一定的操作。例如:printstar();3.函数调用的几种方式(2)函数表达式(函数调用出现在表达式中)一般形式:变量名=函数表达式

这时要求函数带回一个确定的值以参加表达式的运算。例如:c=3+max(a,b);注意:无返回值函数的调用,不能出现在表达式中。函数调用作为一个函数的实参。例如:m=max(a,max(b,c));(3)函数参数(函数调用出现函数参数中)值传递:

在调用函数时,实参将值传递给形参。C语言规定,实参对形参的数据传递是“值传递”,即单向传递。在调用函数时,给形参分配存储单元,并将实参对应的值传递给形参,调用结束后,形参单元被释放,实参单元仍保留并维持原值。

因此,在执行一个被调用函数时,形参的值如果发生变化,并不会改变主调函数中实参的值。7.1.4函数参数的传递方式共

81页第18

页例如:voidadd(inta,intb){a+=3;b+=6;printf(“a=%d,b=%d\n”,a,b);}

main(){intx=1,y=2;add(x,y);printf(“x=%d,y=%d\n”,x,y);}输出结果:a=4,b=8函数的调用值传递x=1,y=2执行函数体返回共

81页第19

值传递的优点:被调用的函数不可能改变调用函数中变量的值,而只能改变它的局部的临时副本。

值传递的缺点:每个形式参数仅能传递一个数据,不适用需要在函数之间传递大量数据。

地址传递:将实参的地址传递给形参,实参和形参指向同一内存空间,对形参的修改,可以直接影响实参。7.1.4函数参数的传递方式(续)共

81页第20

页7.1.5函数的返回值2.函数的返回值语句:return语句

一般形式:

return(表达式);

或return表达式;

定义:通过函数调用使主调函数得到一个确定的值,称为函数的返回值。注意不要丢掉;可以省略括号功能:将表达式的值带回主调函数。共

81页第21

页说明:⑵一个函数中可以有多个return语句,但是一次函数执行只能执行其中的一个。当执行到某个

return语句时,则终止函数执行,并带回函数值。fun(intx){if(x<1)return2*x+1;elseif(x<=10)returnx*x;elsereturn3*x–10;}⑴return后面的值可以是一个表达式,例如:

z=x>y?x:y;return(z);return(x>y?x:y);

等效共

81页第22

页说明(续):⑷若函数体内没有return语句,就一直将函数执行完,再返回调用函数,返回一个不确定的值。⑶

return后面可以无“返回值”(即return;),则该return语句只起到终止函数执行,返回主调函数的作用。共

81页第23

页intmax(x,y)intx,y;{intz;if(x>y)z=x;elsez=y;

return(z);}返回整型函数值intmax(x,y)intx,y;{intz;if(x>y)z=x;elsez=y;

return;}无返回值

max(x,y)

intx,y;

{intz;

if(x>y)z=x;elsez=y;

}无返回语句在此返回缺省类型说明

函数返回值共

81页第24

页3.函数值的类型

函数定义时应该指定函数的类型(即函数值的类型),应该与return语句的类型一致。说明:⑴凡不加类型说明的函数,一律自动按整型处理。⑵如果函数类型和return语句的类型不一致,以函数类型为准。对数值型数据,可以自动进行类型转换。既函数类型决定返回值的类型。⑶如果函数无返回值,可以将函数定义为“无类型”void

(或称“空类型”)。例如:voidprint_star(){……}注意:函数中没有return语句,函数带回的是一个不确定的值。为明确表示不带回值,可以用void定义。共

81页第25

页例:编写计算的程序。程序2:floatsum(n)intn;{inti;floats=0;for(i=1;i<=n;i++)s+=1.0/i;return(s);}main(){intn;floatx;n=20;x=sum(n);printf("x=%f",x);}voidsum(n)intn;

{inti;floats=0;

for(i=1;i<=n;i++)s+=1/(float)i;

printf("s=%f",s);}

main(){intn;

n=20;

sum(n);

}程序1:程序运行结果:s=3.597740调用函数时,变量做函数实参,它和对应的形参各自占用独立的存储单元。共

81页第26

页例:阅读程序

floatadd(x,y)floatx,y;{floatz;z=x+y;return(z);}

main(){floata,b;scanf("%f,%f",&a,&b);printf("sumis%f\n",add(a,b));}

add函数程序运行:3.6,5.5<回车>sumis9.100000以上程序另一写法:

main(){

floatadd();

floata,b;scanf("%f,%f",&a,&b);printf("sumis%f",add(a,b));}floatadd(x,y)floatx,y;{floatz;z=x+y;return(z);}/*定义add函数*/程序运行结果:3.6,5.5<回车>sumis9.100000主函数在前面子函数在后面对被调用函数的说明共

81页第28

页7.1.6函数的说明⒈对被调用函数说明的前提条件

被调用函数必须是已存在的函数,例如用户自定义函数或库函数。2.被调用函数是用户自定义函数的函数说明

同变量一样,函数的调用也应该遵循“先声明,后使用”的原则。

如使用用户自定义函数,而且主调函数和被调用函数在同一个文件中,应该在主调函数中说明被调函数的类型。其说明形式如下:共

81页第29

页函数说明的一般形式:

类型标识符函数名(类型1,类型2,……);或类型标识符函数名(类型1形参1,类型2形参2,……);功能:通知编译程序函数值是什么类型,有多少参数及它们各自的类型,为编译程序进行类型检查提供依据。main(){

floatadd(floatx,floaty);

floata,b,c;scanf(“%f,%f”,&a,&b);c=add(a,b);printf(“sumis%f”,c);}/*定义add函数*/floatadd(floatx,floaty){floatz;z=x+y;return(z);}对被调用函数的说明作为表达式被调用运行结果:3.6,5.5sumis9.100000或:类型标识符函数名();共

81页第30

页3.函数说明和函数定义的区别

函数说明的作用是把函数的名字、函数类型以及形参的类型、个数和顺序通知编译系统,以便在调用该函数时系统按此进行对照检查。

函数定义是指对函数功能的确立,包括指定函数名、函数值类型、形参及其类型、函数体等,它是一个完整的、独立的函数单位。

函数说明与函数定义的首部唯一区别:函数说明语句的()之后必须有分号,而函数定义首部的()之后没有分号。函数定义只能一次函数说明可以多次共

81页第31

页4.以下三种情况可以省略被调用函数的说明⑴函数的返回值为整型或字符型时,可以不进行函数声明,系统按整型处理。main(){inta,b,c;scanf(“%d,%d”,&a,&b);c=max(a,b);printf(“Maxis%d”,c);}max(intx,inty){intz;z=x>y?x:y;return(z);}可省略函数说明该函数没有加类型说明,为整型函数.共

81页第32

页⑵被调用函数的定义在主调函数之前,可以省略声明。floatadd(floatx,floaty){floatz;z=x+y;return(z);}main(){floata,b;scanf(“%f,%f,“&a,&b);printf(“sumis%f”,add(a,b));}被调函数在主调函数之前主调函数在被调函数之后共

81页第33

页⑶如果已在所有函数定义之前,在文件的开头,在函数的外部已说明了函数类型,则在各个主调函数中不必对所调用的函数再作声明。charletter(char,char);floatf(float,float);inti(float,float);main(){…….}charletter(charc1,charc2){……}floatf(floatx,floaty){……}inti(float,float){……}此处不必说明在所有函数之前说明函数类型定义函数letter、f和i共

81页第34

页#include“stdio.h”

/*调用输入输出函数*/#include“math.h”

/*调用数学函数*/#include“string.h”

/*调用字符,字符串函数*/#include“graphics.h”

/*调用图形函数*/用户也可建立自己的库函数,这是高级应用的内容。5.库函数及调用

库函数:由人们根据需要编制并提供给用户使用的一些基本函数,在用户定义的函数中常常调用这些函数。方法:在文件的开头用#include

命令将需要的库函数包含到文件中。共

81页第35

页7.2数组作函数参数数组元素可以作函数的实参数组名可以作函数的实参和形参多维数组可以作函数参数

7.2.1.数组元素作函数实参

由于表达式可以做实参,数组元素可以作为表达式的组成部分,因此,数组元素可以做函数的实参,与变量一样,是单向传递,即“值传送”方式。

例如:

inta[10];······x=power(a[9],5);数组元素作实参共

81页第36

页7.2.2数组名作函数的参数

可以用数组名作函数参数,此时实参和形参都用数组名。由于数组名代表的就是数组在内存中存放区域的首地址。把数组名作为函数参数来实现大量数据的传递是一个非常好的数据传递方法。这种传递方式是“地址传递”共

81页第37

页有两种形式:①

[函数值类型说明符]函数名(类型说明符数组名[],……)

{函数体}

[函数值类型说明符]函数名(数组名,……)

类型说明符数组名[];

{函数体}

1.一维数组作函数参数2.数组作函数形参的函数调用方式函数名(数组名,………)共

81页第38

页说明:在主调函数和被调用函数中分别定义数组。实参数组和形参数组类型要一致。实参数组和形参数组大小可以不一致,形参数组可以不指定大小。(这里指一维数组)。函数调用时,形参数组将获得实参数组的起始地址。共

81页第39

页例:编写函数,求n个数组元素的算术平均值。doubleaverage(inta[],intn){inti;doubles=0;for(i=0;i<n;i++)s=s+a[i];returns/n;}主函数调用如何编写?

main(){intb[3]={1,2,3};doubles;s=average(b,3);printf(“%f\n”,s);}形参数组不指定大小,数组名后跟一个空方括号这是数组作形参时常使用的技巧实参a获得b的起始地址数组名做函数是“地址传递”。也就是把实参数组的起始地址传递给形参数组,这样二者共占一段内存单元。因此,形参数组各元素的值如果发生变化会使实参数组各元素的值发生同样的变化。例:阅读下列程序,指出输出结果。main(){voidswap();/*函数声明*/intb[2]={10,2};swap(b);printf(“b[0]=%d,b[1]=%d\n”,b[0],b[1]);}

voidswap(inta[]){intt;t=a[0];a[0]=a[1];a[1]=t;}共

81页第41

页数组bbb[1]b[0]102数组a数组bb,ab[1]b[0]102a[1]a[0]函数开始调用之前函数开始调用,实参数组b将起始地址传递给形参数组a,二者共占一段内存单元数组a数组bb,ab[1]b[0]210a[1]a[0]swap函数执行过程中,a[0]与a[1]的值交换数组bbb[1]b[0]210函数调用结束后共

81页第42

页例:编写一个函数.

功能:在n个整数中,找出数值最大的数。给定10个整型数,找出其中数值最大的数。intmax(a,n)inta[],n;{intm,i;m=a[0];for(i=1;i<n;i++)if(a[i]>m)m=a[i];return(m);}子函数:main(){intx[10],amax;inti;for(i=0;i<10;i++)scanf("%d",&x[i]);

amax=max(x,10);printf(“amax=%d",amax);}主函数:前面所学内容共

81页第43

页例:用选择法对数组中10个整数按由小到大排序.方法:写一个函数sort(array[],n):对数组元素按由小到大排序。写主函数:输入array数组,调用sort函数,输出排序后的array数组。voidsort(intarray[],intn){inti,j,t;for(i=0;i<n-1;i++)for(j=i+1;j<n;j++)if(array[j]<array[i]){t=array[j];array[j]=array[i];array[i]=t;}}前面所学内容共

81页第44

页main(){inta[10],i;printf(“enterarray:\n”);for(i=0;i<10;i++)scanf(“%d”,&a[i]);sort(a,10);printf(“thesortedarray:\n”);for(i=0;i<10;i++)printf(“%d”,a[i]);printf(“\n”);}由于地址传递,实参数组a改变数组名做参数的好处:⑴由于只需复制一个地址值,而无须复制全部需要处理的数据,因此节约存储空间并提高效率。⑵由于主调函数和被调函数是在相同的内存区域上对数据进行操作,因此可以实现数据的同步更新。共

81页第45

页有两种形式

(形式基本同一维)①[函数值类型说明符]函数名(类型说明符数组名[][正整型常量表达式],……){函数体}②[函数值类型说明符]函数名(数组名,……)

类型说明符数组名[][正整型常量表达式];{函数体}7.2.3二维数组作函数参数“行”可以不确定“列”必须确定!!共

81页第46

页说明:形参数组定义时可以指定每一维的大小,也可以省略第一维的大小,不允许省略第二维以及其他高维的大小.例如:intarray[3][10];或intarray[][10];是一样的!但

intarray[3][];和intarray[][];是错误的!实参数组可以大于形参数组。(行可以不同,列必须相同)例如:实参数组定义为:intarray[5][10];

形参数组定义为:intarray[3][10];

这时形参数组只取实参数组的一部分,其余部分不起作用。共

81页第47

页例:阅读程序,指出运行结果。

voidadd1(inta[][3],intn){inti;for(i=0;i<n;i++)++a[i][i];}

main(){intx[3][3]={0,1,2,3,4,5,6,7,8},i;add1(x,3);for(i=0;i<3;i++)printf("%d",x[i][i]);printf("\n");}程序运行结果为:159注意:二维数组的调用注意:二维数组的定义共

81页第48

页例:写函数打印n行10列二维数组,其中n是任意整数。

voidprint_array(inta[][10],intn){inti,j;for(i=0;i<n;i++){for(j=0;j<10;j++)printf(“%3d”,a[i][j]);printf(“\n”);}}例:写函数交换任意一个n*10的二维数组的i,j两行

voidexchange(inta[][10],inti,intj){intk,t;for(k=0;k<10;k++){t=a[i][k];a[i][k]=a[j][k];a[j][k]=t;}}例:编写函数,计算两个3行4列的矩阵之和。并求:C3X4=A3X4+B3X4voidqiuh(floatx[][4],floaty[][4],floatz[][4],intn){inti,j;for(i=0;i<n;i++)for(j=0;j<4;j++)z[i][j]=x[i][j]+y[i][j];}main(){floata[3][4],b[3][4],c[3][4];inti,j;for(i=0;i<3;i++)for(j=0;j<4;j++)scanf(“%f%f”,&a[i][j],&b[i][j]);qiuh(a,b,c,3);for(i=0;i<3;i++){for(j=0;j<4;j++)printf(“%10.2f”,c[i][j]);printf(“\n”);}}注意函数的定义和函数的调用共

81页第50

页7.3函数的嵌套调用和递归调用7.3.1函数的嵌套调用嵌套定义:在定义一个函数时,该函数体内包含另一个函数的定义。嵌套调用:在调用一个函数的过程中,又调用另一个函数。C语言不允许嵌套定义,但可以嵌套调用。在调用一个函数的过程中,又调用另一个函数。共

81页第51

页函数的嵌套调用main函数{……

……

调用函数A;

……}函数A{……

……

调用函数B;

……}函数B{……

……

……}调用调用返回返回共

81页第52

页例:阅读程序,指出运行结果。main(){inta=0,b=0,b1(int,int);printf("b1=%df1=%d\n",b1(a,b),f1(

));}b1(intd,inte){intf1(

),f;d=5;e=10;f=f1(

)+d+e;returnf;}f1(){intc,i=1;c=15;while(i<=3){c*=i;i++;}returnc;}程序执行结果:

b1=105f1=90f1返回的是整型可以省略声明这个说明也可以省略函数声明。也可写成原型:b1(intd,inte)此例b1返回的是整型也可以不说明共

81页第53

页7.3.2函数的递归调用1.递归的概念:在调用一个函数的过程中直接或间接地调用该函数本身。f函数调用f函数直接递归调用intf(intx){inty,z;…..z=f(y);……return(2*z);}

81页第54

页intf1(intx)

{inty,z;…..z=f2(y);……return(2*z);}intf2(intt)

{inta,c;…..c=f1(a);……return(3+c);}间接递归调用共

81页第55

页递归函数的执行过程:

递归调用:记住本次现场,递归调用。终了调用:返回上次调用现场。特点

是无终止的递归调用,因此,应该给定一个限制递归次数的条件。

f1函数调用f2函数f2函数调用f1函数共

81页第56

页intf(intx){inty;if(x==0||x==1)return(3);y=x*x-f(x-2);returny;}main(){intz;z=f(3);printf(“%d\n”,z);}A)0B)9C)6D)8例:阅读以下程序段,运行后的结果是:举例:编写计算n!的程序。

n*(n-1)!当n>1longintfact(intn){longintf;if(n==0||n==1)f=1;elsef=n*fact(n-1);returnf;}main(){longintred;intn;scanf("%d",&n);red=fact(n);printf("red=%ld",red);}假如求5!,则程序执行结果为:red=1201当n=0,n=1n!=共

81页第58

页f=3*fact(2)f=1*2*3=6fact函数

n=3f=2*fact(1)f=1*2=2fact函数

n=2

调用fact函数时,总是从fact的第一条语句开始执行;执行到return语句,总是返回到该次调用的调用位置继续执行调用函数。fact函数的调用过程:main()fact(5)输出fact(5)f=5*fact(4)f=1*2*3*4*5=120fact函数

n=5f=4*fact(3)f=1*2*3*4=24fact函数

n=4第一次调用第二次调用第三次调用第四次调用第五次调用返回返回返回返回返回共

81页第59

页变量的数据类型char型

int型

float型

double型总结:数据类型决定为变量分配的内存单元的长度,数据的存放

形式。(从程序设计角度,决定了可以表示的数的范围)问题:1.何时为变量分配内存单元?

2.变量位于内存的什么位置?

3.变量的有效作用范围?7.4变量的作用域和存储方法共

81页第60

变量的作用域和生存期

变量的作用域

指一个变量在程序中的有效范围。

C语言规定:凡是在函数内定义的变量,它的作用域仅仅是包含这个变量定义的复合语句;而在函数体外定义的变量,它的作用域是从定义点到文件尾。

变量的生存期指程序在执行期间,变量存在的时间间隔,即从给变量分配内存,至所分配内存被系统收回的那段时间。

C语言规定:凡是出现在静态数据区的变量,生存期都是从程序开始执行到程序结束;而出现在静态区之外的变量,生存期仅仅是从函数开始执行到函数执行结束这段时间。共

81页第61

页1.局部变量(内部变量)定义:在函数内部定义的变量,只能在本函数内部使用,称为局部量。7.4.1局部变量和全局变量(从变量的作用域分)如:floatf1(inta){intb,c;…..{charf2(intx,inty){inta,b;……}main(){intm,n;…….{a,b,c在函数f1中有效x,y,a,b在函数f2中有效m,n在主函数中有效共

81页第62

页主函数main定义的变量只在主函数中有效,主函数不能使用其它函数定义的变量。不同函数可以使用相同名字的变量,它们在内存中占不同的单元,互不影响。(如,前例f1和f2中的a,b变量)形式参数也是局部变量。在一个函数内部,可以在复合语句中定义变量,这些变量只在本复合语句中有效。

关于局部变量几点说明:如:main(){inta,b;/*a,b在整个main函数内有效*/……

{intc;/*c仅在本复合语句内有效*/c=a+b;……

}…….}共

81页第63

页2.全局变量

程序中,在函数之外定义的变量称为外部变量,即全局变量。全局变量可以为本文件中的其他函数所共用,但是,它的有效范围是从定义变量的位置开始到源文件的结束。如:intp=1,q=5;floatf1(inta)

{intb,c;…..

{charc1,c2;charf2(intx,inty)

{inta,b;……

}main()

{intm,n;…….

{全局变量c1,c2的作用范围全局变量p,q的作用范围共

81页第64

页从定义变量的位置开始到本文件结束,这段程序中的函数可直接使用全局变量。(注意全局变量的有效范围)如果在同一源文件中,全局变量和局部变量同名,则在局部变量的作用范围内,全局变量不起作用。

关于全局部变量几点说明:共

81页第65

页例如:#include“stdio.h”inta=7,b=10;main(){inta=5,c;c=a+b;printf(“c=%d\n”,c);}运行结果:c=15全局量的a没有起作用共

81页第66

页使用全局变量的优点:函数间数据联系:同一文件中的一些函数引用全局变量,当某个函数中改变了全局变量的值,其它函数中的全局变量值也随之改变。函数可以得到多个返回值。缺点:全局变量在程序的全部执行过程中都占用存储单元,而不是仅在需要时才开辟单元。降低函数的通用性,因为函数在执行时要依赖其使用的全局变量。(对函数的移植带来不便)使用过多,降低程序的清晰性,难以判别全局变量的值。

提示:全局变量应尽可能少用。共

81页第67

两种:静态存储方式:程序运行期间分配固定存储空间的方式。动态存储方式:程序运行期间根据需要进行动态的分配存储空间的方式。程序区静态存储区动态存储区全局变量,局部静态变量形式参数局部变量(自动)函数调用的现场保护和返回地址7.4.2变量的存储方法运行期间的C程序占用的内存由3部分构成:共

81页第68

页变量存贮类型有四种:1.自动变量(auto)2.静态变量(static)3.寄存器变量(register)4.外部变量(extern)

局部变量全局变量共

81页第69

页1.局部变量的存储方法(1)自动变量(auto)

动态分配存储空间的变量。如:函数中的局部变量、函数的形参、复合语句中的局部变量,称为自动变量,用关键字auto作为存储类型说明。如:intf(inta){

autointb,c=3;

…}自动变量被分配在动态存储区,用前分配,用后释放。实际上不加特殊声明(static)的局部变量都是自动变量,因此在定义自动变量时,关键字可以省略。intf(inta){intb,c=3;

…}写成为:共

81页第70

页(2)用(static)声明局部变量

静态存储方式,整个程序运行期间都不释放。定义形式:在变量名前面加关键字static

static类型说明符变量名;编译时赋初值,每次调用时不赋初值,只保留调用结束时变量的值。如果局部静态变量不赋初值,编译时自动赋0,而自动变量不赋初值,其值不确定。局部静态变量只允许所在函数引用,其它函数不能引用。共

81页第71

页例如:f(inta){intb=0;staticintc=3;b=b+1;c=c+1;return(a+b+c);}main(){inta=2,i;for(i=0;i<3;i++)printf(“%d”,f(a));}运行结果为:

789第一次调用开始第一次调用结束第二次调用开始0b34410c共

81页第72

页(3)寄存器变量(register)定义:直接放置在运算器的寄存器中的变量称为寄存器变量说明方式:在变量名前面加关键字register

register类型说明符变量名;只有局部自动变量和形式参数才可以声明为寄存器变量,因为register变量在函数调用结束时必须释放。如:intfac(intn){registerinti,f=1;for(i=1;i<=n;i++)f=f+i;return(f);}寄存器变量的说明注意:局部静态变量不能声明为寄存器变量共

81页第73

页2.全局变量的存储方法(1)外部全局变量

在多个源程序文件的情况下,如果在文件B中要引用文件A中所定义的全局变量,则应该在文件B中对所要引用的变量,用extern说明。例如:

prog1.c的内容如下:inta;main(){x=6;f1();}voidf1(){a+=2;printf("a=%d\n",a);f2();}prog2.c的内容为:externinta;voidf2(){a++;printf("a=%d\n",a);}对文件prog1.c中全局变量a的声明共

81页第74

页(2)静态全局变量若在一个文件中定义的全局变量仅限于本文件引用,而不能被其它文件访问,则可以定义为静态全局变量。例如:staticintx;

例如:file1.cfile2.cstaticinta;externinta;main()fun(intn);{{…..}…..}

staticinta只能用于file1.c,虽然file2.c中将同名变量inta说明为extern,但仍无法使用file1.c中的a变量。共

81页第75

页7.5内部函数和外部函数1.内部函数(静态函数)定义:如果一个函数只能被本文件中其它函数调用,称为内部函数。定义格式:

static类型标识符函数名(形参表)函数体例如:staticintfun(a,b){······}作用:函数的作用域限于所在文件,不同文件中同名函数互不干扰,便于程序的格式化。共

81页第76

页2.外部函数定义:如果一个函数允许被其它文件调用,称为外部函数。定义格式:

[extern]类型标识符函数名(形参表)函数体

例如:externintfun(inta,intb){······}

或intfun(inta,intb){······}通常不加static标识符的函数都是外部函数(我们前面所有函数)。共

81页第77

页3.标号的生存期及作用域生存期

在C语言中,由于函数的生存期是全程的,即从程序开始至程序结束,标号是函数的一部分,标号的生存期自然是全程的。作用域

C语言规定,标号的作用域仅为定义标号的函数,即不允许用goto语句从一个函数转向另一个函数。

81页第78

页函数间的数据传递

——三种传递方式返回值参数全局变量共

81页第79

页函数的返回值通过return语句返回。return语句只能把一个返值传递给调用函数。返回值的类型为定义的函数类型,若return语句中表达式类型与函数类型不一致,则转换为函数类型。返回值可以是数值,也可以是地址。当返值是地址时,应该用指针接受它。无返回值的函数,定义为void类型。共

81页第80

页函数间的参数传递在函数被调用时才分配形参的存储单元。实参可以是常量、变量或表达式。实参类型必须与形参相符。传递时是传递参数值,即单向传递。使用地址作为参数,可以返回函数处理结果。数组作为参数时的情况。数组元素作实参,与单个变量一样。数组名作参数,传送的是数组首地址。共

81页第81

页使用全局变量传递数据在所有函数之外说明的变量是全局变量,它在所有函数中都是可见的。利用全局变量的这个特性,可以在函数间传递数据共

81页第82

页作业

第七章(笔头作业)练习二、三

上机编程题

温馨提示

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

评论

0/150

提交评论