




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第5章函数
2012年6月21日星期四
2012-6-21
2012-6-212
结构化程序设计方法,从程序实现的角度看就是
模块化程序设计,就是将程序模块化,即在程序
设计中通常将一个大的程序按功能进行分割成一
些模块,使每个模块都成为功能单一、结构清晰、
接口简单、容易理解的小程序。在C语言中是通
过函数来实现模块化程序设计的,即将那些较小
的功能单一的程序模块称之为函数,通过对函数
的调用实现特定的功能。所以较大的C语言应用
程序,往往是由多个函数组成的,每个函数分别
对应各自的功能模块,通过函数的定义把实现的
细节封闭起来,通过函数调用组合各种功能。
2012-6-213
c语言提供以下一些功能来支持模块化软件开发:
(1)函数式的程序结构。程序整体由一个或多个
函数组成。
(2)允许通过使用不同存储类别的变量,控制模
块内部及外部的信息交换。
(3)具有编译预处理功能,为程序的调试、移植
提供了方便。
2012-6-214
5.1函数概述
用C语言设计程序来求解任何一个问题时,主要任务
就是编写函数。
进行C程序设计时一般采用自顶向下、逐步细化的
方法设计程序结构,即先集中考虑main函数中的算法。
当main函数中需要使用某一功能时,就先写上一个调用
具有该功能的函数的表达式。这时只需知道函数具有什
么功能,如何与程序通信(输入什么,输出什么),函
数的具体实现先不去处理。设计完main()函数的算法并
检验无误后,再开始考虑它所调用函数的具体实现。在
这些被调用的函数中,若在库函数中可以找到,那就直
接使用,否则就动手设计这些函数。
2012-6-215
【例5.1】分别求两个长方形的面积。
分析:采用模块化程序设计的思想,将计算长方形面积的
代码段提炼出来,写成函数,当需要这段代码时,就调
用该函数。
include<stdio.h>
intmain()/*先设计main函数*/
(
inta,b,c,d,s1,s2;
printf("Pleaseinputthewidthandtheheight(two
rectangular):");
nn
scanf(%d%d%d%d,&a5&b,&c,&d);/*调用输入库函数*
s1=area(a,b);/*调用自定义函数area*/
s2=area(c,d);/*再次调用自定义函数area*/
printf("theareaofthefirstrectangularis%d\nH,s1);
printf("theareaofthesecondrectangularis%d",s2);
return0;"
-2012-6-216
intarea(intx,inty)/*再设计自定义函数area7
(
intz;
z=x*y;
returnz;
)
由此可以看出,在c程序设计中使用函数可以
减少重复编写程序的工作量,使程序便于调试
和阅读。
2012-6-217
5.2函数的分类
C语言中可从不同的角度给函数分类。
1.从函数定义的角度
(1)库函数
由C系统提供,用户无须定义,也不必在程序中
作类型说明,只需在程序前包含有该函数原型的
头文件即可在程序中直接调用。在前面章节中用
至U的printf、scanf>getchar>putchar等函数均属
库函数。
C语言提供了丰富的库函数,字符类型函数、转换
函数、字符串函数、数学函数、输入输出函数等
等,详见附录IV。
2012-6-218
(2)用户自定义函数
系统提供的库函数不能完全满足用户的特
殊需求时,由用户按需要自己设计的函数。
用户可按C语言的函数规则定义其函数名称、
使用的参数、完成的功能和运行的结果。
如例5.1中的area函数是用户自定义函数。
2012-6-219
2.从主调函数和被调函数间数据传送的角度
(1)无参函数
函数定义、函数说明及函数调用中均不带
参数。主调函数和被调函数之间不进行参
数传送。此类函数通常用来完成一组指定
的功能,可以返回或不返回函数值。
(2)有参函数(带参函数)
在函数定义及函数说明时都有参数,称为
形式参数(简称为形参)。在函数调用时也
必须给出参数,称为实际参数(简称为实
参)。进行函数调用时,主调函数将把实
参的值传送给形参,供被调函数使用。
2012-6-2110
5.3函数的定义和调用
•5.3.1函数的定义
函数的定义格式为:
类型标识符函数名([形式参数列表])
(
类型声明部分
执行语句部分
}
2012-6-2111
说明:
(1)函数名是由用户定义的标识符,是唯一
标识一个函数的名字,它的命名规则同变
量的命名规则完全一样。同一个程序中不
同的函数名字不能相同。
(2)类型标识符说明了函数的类型,即函数
返回值的类型。
(3)若形式参数列表为空,则该函数是无参
函数,此时函数名后面跟一对空圆括号。
2012-6-2112
(4)若有形式参数列表,则该函数是有参函
数。形参表用于调用函数和被调用函数之
间进行数据传递,形参表中的参数可以是
各种类型的变量,各参数之间用逗号间隔。
形参是变量,在形参表中应给出形参的类
型说明。
(5)由左、右花括号括起来的部分称为函数
体,由类型声明部分和执行语句部分组成。
类型声明部分用于对函数内所使用的变量
的类型进行说明;执行语句部分由C语言的
基本语句组成,它是函数功能的核心部分。
声明语句须放在执行语句之前。
2012-6-2113
(6)允许程序设计中使用空函数,该函数什
么也不做,没有任何实际作用,先占一个
位置,在程序需要扩充功能时,再用一个
编好的函数取代它。
空函数的形式为:
void函数名()
()
2012-6-2114
【例5.2]定义无参函数。
include<stdio.h>
voidprint()
(
printfCHello!");
)
intmain()
(
print();/*调用函数print*/
return0;
)
运行结果如下:
Hello!
2012-6-2115
【例5.3]定义有参函数。
include<stdio.h>
intmain()
(
intx,y,z;
printf(Tleaseinputtwointeger:");
HH
scanf(%d%d,&xJ&y);
z=max(x,y);/*调用函数max7
printf(Hthemaxis%d.",z);
return0;
)
2012-6-2116
intmax(intm,intn)
/*定义函数max,求两个数的最大值*/
(
ints;/*函数体的类型声明部分*/
if(m>n)/*函数体执行语句部分的开始7
s=m;
else
s=n;
returns;/*函数体执行语句部分的结束*/
)
2012-6-2117
由上述两个例子可以看出,在C程序中,
一个函数的定义可以放在任意位置,既可
放在主函数main之前,也可放在main之后。
在C语言中,所有的函数定义,包括主函
数main在内,都是平行的。也就是说,在
一个函数的函数体内,不能再定义另一个
函数,即函数不能嵌套定义。
2012-6-2118
5.3.2函数的调用
1.函数的一般调用形式
函数名(实际参数列表)
说明:
若是调用无参函数,则“实际参数列表”可
以没有,但圆括号不能省略,如例5.2。若
“实际参数列表”包含多个实参,则各参
数间用逗号隔开,如例5.3。
2012-6-2119
2.函数的调用方式
按函数在程序中出现的位置来分,有以下三种函数调用方式。
(1)函数语句
把函数调用作为一个语句,如例5.2中“print。;”。
(2)函数表达式
函数出现在一个表达式中,这种表达式称为函数表达式。
例如:z=max(x,y);
或z=2*max(x,y);
函数max是表达式的一部分,它的值乘以2再赋给z。
(3)函数参数
函数调用作为一个函数的实参。
例如:p=max(max(x,y),z);
这里,max(x,y)是一次函薮施用,它的值作为max另一次调用
的实参。p的值就是x,y,z三者的最大值。
又如:printf("%d",max(x,y));
这里,函羲调甫max(x,y)作Rprintf函数的一个参数。
2012-6-2120
3.被调用函数的使用说明
在程序中调用另一个函数时,要满足以下三个条件。
(1)被调用函数可以是已经存在的用户自定义函数或者
是系统库函数。
(2)如果调用库函数,应该在本程序开头使用箱的1加6命
令将调用有关库函数时所需用到的信息“包含”到本程
序中。
例如:
include<stdio.h>/*输入输出库函数*/
include<math.h>/*数学库函数*/
2012-6-2121
(3)如果调用用户自定义的函数,且该函数与对该
函数的调用函数在同一个源文件中,特别是函数中
调用函数,则在主调函数中必须对被调用函数作类
型声明。对被调用函数进行类型声明就是告诉系统,
在本函数中将要用到的函数是什么类型,即函数的
返回值是什么类型,以便按声明的类型对函数值作
相应的处理。
函数声明的一般格式为:
类型标识符函数名(类型标识符形参名,类型标识
符形参名,…);
2012-6-2122
说明:
①对被调用函数声明时,可以省略形参名。函数声明语句后
面的分号不能省略。
②被调用函数的返回值是整型或字符型时,可以不对被调用
函数进行声明,而直接调用。这时系统将自动对被调用函
数返回值按整型处理。
如例5.1和例5.3中的被调函数area和被调函数max的返回值
均为整型,所以在主调函数main函数中均未对被调函数作
类型声明。
③如果被调用函数的定义出现在主调函数之前,可以不必对
被调用函数加以声明。
如例5.2中被调函数print在主调函数main之前定义,所以在
主调函数main中不需要对被调函数print作类型声明。
④如果在程序的开头(在所有函数之前),已对本程序中所
调用的函数进行了声明,则在各主调函数中不必对其所调
用的函数再作声明。
2012-6-2123
【例5.4】计算n!。
include<stdio.h>
intmain()
longfac(int);/*对被调函数fac作类型声明,省
略了参数名*/
intn;
longlayer;
print^Tleaseinputn:H);
scanf(”%cT,&n);
layer=fac(n);
printf(,,n=%d,%d!=%ld,,,n,n,layer);
return0;
}________________________________________
2012-6-2124
longfac(intx)
此例是在主调函数main中对被调函数
longy;fac作类型声明,声明语句double
fac(int)也可以放在程序的开头,即:
inti;
#include<stdio.h>
y=1;doublefac(int);/*对被调函数fac
for(i=1;i<=x;i++)作类型声明*/
intmain()
y=y*i;
returny;
)
)doublefac(intx)/*定义函数fac*/
)
2012-6-2125
关于函数调用还需要说明的是,在C程序中,
main函数是主函数,它可以调用其它函数,而不
允许被其它函数调用。因此,C程序的执行总是
从main函数开始,完成对其它函数的调用后再返
回到main函数,最后由main函数结束整个程序。
一个C源程序必须有,也只能有一个主函数main。
函数的使用和变量一样,一般要求先定义后使用。
2012-6-2126
5.4函数的返回值
函数的返回值是指函数被调用之后,执行函数体
中的程序段所取得的并返回给主调函数的值。函
数调用的目的通常是为了得到一个计算结果即函
数值。在C程序中,利用返回语句return将计算结
果返回给主调函数,同时,也使程序的执行流程
转到主调函数的下一条语句去执行。
返回语句的格式为:
return(表达式);
或者
return表达式;
2012-6-2127
说明:
(1)函数的返回值只能通过return语句返回给
主调函数。在函数中允许有多个return语句,
但每次调用只能有一个return语句被执行,因
此只能返回一个函数值。
(2)返回值的类型和函数定义中函数的类型应
保持一致。如果两者不一致,则以函数类型为
准,自动进行类型转换。
(3)系统默认的函数返回值类型为整型,因此
当函数返回值为整型时,在函数定义时可以省
去返回值类型说明。
2012-6-2128
(4)当函数没有返回值时,函数的返回值类型可以
定义为“空类型”,类型说明符为“void”。在调
用无返回值的函数时,往往是以单独的调用语句
出现的,即在主调函数中就不能使用被调函数的
函数值了。为了使程序有良好的可读性并减少出
错,凡不要求返回值的函数都应定义为空类型。
假设将例5.4中函数fac定义为void,即:
voidfac(intx)
)
则在主函数中写语句:layer二fac(n);就是错误的
2012-6-2129
【例5.5】求两个数的最大值。
主函数main()与例5.3的相同,max函数改写如下:
max(intm,intn)
(
if(m>n)
returnm;
else
returnn;
)
函数max的返回值为整型,定义函数时省略了类
型,所以也未对max函数作类型声明。
2012-6-2130
5.5函数的参数及参数的传递
5.5.1函数的参数
1,形式参数(简称形参)
在定义函数时函数名后面括弧中的变量名称为
形参,即形参出现在函数定义中。
形参变量只有在被调用时才为其分配临时内存
单元,在调用结束时,即刻释放所分配的内存
单元。因此,形参只在函数内部有效。函数调
用结束返回主调函数后则不能再使用该形参变
量。
2012-6-2131
2.实际参数(简称实参)
在调用函数时,函数调用语句中函数名后面括弧
中的参数称为实参。实参出现在主调函数中。
实参可以是常量、变量、表达式、函数等,无论
实参是何种类型的量,在进行函数调用时,它
们都必须具有确定的值,以便把这些值传送给
形参。因此应预先用赋值、输入等办法使实参
获得确定值。
实参和形参在数量、类型、顺序上应严格一致,
否则会发生“类型不匹配”的错误。
2012-6-2132
5.5.2参数的传递方式
实参和形参的功能是作数据传送。在c语言中实
参和形参之间的数据传递有两种方式。
1.传值
调用函数时将实参的值传递给形参,形参值的改
变不会影响实参。调用结束后,形参所占用的内
存单元被释放,实参仍保持原值不变。该方法只
能由实参向形参传递数据,即该方式是单向传递。
2012-6-2133
【例5.6]传值方式举例。
#include<stdio.h>
voidswap(intjnt);/*对被调函数的类型声明*/
intmain()
(
intn,m;
printf(nPleaseinputnumber:");
scanf("%d%d"5&n,&m);
printf(,,n=%d,m=%d\n,,,n,m);
swap(n,m);
printf("n=%d,m=%d\n",n,m);
return0;
)
2012-6-2134
voidswap(intx,inty)
/*函数swap的定义,该函数无返回值7
(
intt;
t=x;
x=y;
y=t;
printf("x=%d,y=%d\n,,,x,y);
)
假定输入n和m的值分别为5和7,运行结果如下:
Pleaseinputnumber:57/
n=5,m=7
x=7,y=5
n=5,m=7
2012-6-2135
•本例中函数swap的功能是交换两个参数的
值。但从运行结果可以看出,调用swap函
数只交换了两个形参的值,而实参的值并
没有交换。
5K!75Kg7
5E77«5
(a)调用swap时,形参分别得到对应实参的(b)执行sw叩,交换了形参的
值图5.1传值方式疆列
2012-6-2136
【例5.7】利用数组元素、表达式作为实参进行参数传递。
#include<stdio.h>
intsum(intjnt);
intmain()
intx=10,y=20,a,bc;
J运行结果如下:
intaa[3]={1,2,3};
x+y=30
a=sum(x,y);
(x+10)=y=40
b=sum(x+10,y);
aa[0]+aa[1]+aa[2]=6
c=sum(sum(aa[0],aa[1]),aa[2]);
printf("x+y=%d\n",a);
printf("(x+10)+y=%d\n",b);
printf("aa[0]+aa[1]+aa[2]=%d\n",c);本例在主调函数main函数中,分别
return0;用零量:x,V、表达式:x+10、数
}组元素:aa[O],aa[1],aa[2]>函
intsum(intm,intn)数值sum(aa[0],aa[1])作为实参单向
给形参传递值。
intp;
p=m+n;
returnp;
Joi2-6-21
37
由此可见,在普通变量或数组元素作为函数
参数时,形参变量和实参变量是在程序运
行时分配的两个不同的内存单元,所进行
的值传递是单向的,即只能从实参传向形
参,不能从形参传回实参。形参的初值和
实参相同,而形参的值发生改变后,实参
的值并不变化,两者的最终值是不同的。
2012-6-2138
2,传地址
在实际应用中,往往需要将形参的值返回给
实参,所以需要双向传递,这时可以使用
传地址方式。
当用表示地址的数组名或者用指针变量(详
见第6章)作为函数参数进行参数传递时就
不是传值,实际上传送的是地址,即把实
参所存放的地址赋予形参。由于形参在调
用时所得到的是实参所指的地址,因而形
参和实参将占用同一片内存空间,即两者
指向同一个对象,因此在被调函数中对形
参所做的操作都会影响到实参。
2012-6-2139
【例5.8】采用插入排序法将数组中元素升序排列。
#include<stdio.h>
#defineN10
voidsort(inta[],intn);
intmain()
(
ints[N],i;
printf("Pleaseinputdata:");
for(i=0;i<N;i++)
scanf("%d",&s[i]);
sort(s,N);
printf("Thelistis(inmain()):");
for(i=0;i<N;i++)
printf("%4d",s[i]);
return0;
2012-6-2140
voidsort(inta[],intn)
int本例中,排序函数sort(inta[],intn)
for(i=0;i<n-1;i++)的两个形参中,a表示数组"n
指定数组的长度。
k=i;
for(j=i+1;j<n;j++)
if(a[j]<a[k])k=j;
if(k!=i)
t=a[k];a[k]=a[i];a[i]=t;
}
}
printf("\nThelistis(insort()):");
for(i=0;i<n;i++)
printf("%4d",a[i]);
2012-6-2141
注意:
用数组名作为函数参数时,必须在被调函数与主
调函数中分别定义数组。在对形参数组定义时不
指定数组的长度,而仅给出类型、数组名和一对
方括号,以便允许同一个函数可根据需要来处理
不同长度的数组;但是为了能使程序了解当前处
理数组的实际长度,往往用另一个参数来表示数
组的长度。当多维数组名作为函数参数时,除第
一维可以不指定长度外,其余各维都必须指定数
组长度。形参数组与实参数组在类型上应该一致,
否则会出错。
2012-6-2142
5.6函数的嵌套与递归调用
5.6.1函数的嵌套调用
C语言中不允许作嵌套的函数定义。因此各
函数之间是平行的,不存在上一级函数和
下一级函数的问题。但是C语言允许在一
个函数的定义中出现对另一个函数的调用。
这样就出现了函数的嵌套调用,即在被调
函数中又调用其它函数。
2012-6-2143
•函数的嵌套调用可以用图5.2表示,这是一
个二层调用的示意图。
main函数fl函数f2函数
①②③
⑤
调用fl函数调用f2函数
⑨⑦
结束返回main函数返回fl函数
图5.2函数嵌套调用示意图
2012-6-2144
【例5.9]计算1!+2!+3!+…+10!
#include<stdio.h>longsum(intn)longfac(intx)
longfac(int);
longsum(int);inti;longy;
intmain()longm=0;inti;
for(i=1;i<=n;i++)y=1;
longs;m+=fac(i);for(i=1;i<=x;i++)
s=sum(10);returnm;y=y*i;
printf("1!+2!+..+10!=%ld",s);}returny;
return0;}
)
2012-6-2145
5.6.2函数的递归调用
在调用函数的过程中又出现直接或间接的调用该函数自身,称为
函数的递归调用。这种函数称为递归函数。C语言允许函数的
递归调用,但是程序中不应出现无终止的递归调用,只应出现
有限次数的。
例如有函数fun如下:
intfun(intm)
intn;
t=fun(n);
returnt;
这个函数是一个递归函数。但是运行该函数时将无休止地调用其
自身,这显然是不正确的。为了防止递归调用无终止地进行,
必须在函数内有终止递归调用的语句。常用的办法是加条件判
断,满足某种条件后就不再作递归调用,然后逐层返回。
2012-6-2146
【例5.10】用递归算法计算n!
用递归法计算n!可用下述公式表示:
n!=1(n=0,1)
nX(n-1)!(n>1)intmain()
include<stdio.h>intn;
longfac(intn)longm;
printf(H\nPleaseinputainteger:");
scanf(”%cT,&n);
longf;
m=fac(n);
if(n==0||n==1)f=1;printf(,,%d!=%ld,,,n,m);
elsef=n*fac(n-1);return0;}
returnf;
)
2012-6-2147
57变量的作用域和存储类型
前面介绍了变量的一些属性及使用方法,本节将从
空间和时间两个不同的角度来描述变量,介绍变
量的作用域和生存期。两者既有联系,又有区别
变量的作用域指一个变量能够起作用(被引用)的
程序范围,即一个变量定义之后,在何处可以使
用该变量。
变量的生存期指程序在执行期间,变量存在的时间
间隔,即从给变量分配内存,至所分配内存被释
放的那段时间。
2012-6-2148
5.7.1变量的作用域
c语言中所有的变量都有自己的作用域。变量
定义的位置,其作用域将不同。C语言中的变
量,按作用域范围可分为两种,即局部变量和
全局变量。
1.局部变量
局部变量也称为内部变量。局部变量是在函数
内作定义说明的。其作用域仅限于函数内,离
开该函数后再使用这种变量是非法的。
2012-6-2149
例如:
intf1(inta)/*函数f1*/
{/*a,b,c在该花括号范围内有效*/
intb,c;
)
intf2(intx)/*函数f2*/
{/*x,y,z在该花括号范围内有效*/
inty,z;
)
intmain()
{/*在该花括号范围内有效*/
2012-6-2150
说明:
(1)主函数中定义的变量也只能在主函数中使用,
不能在其它函数中使用。同时,主函数中也不能
使用其它函数中定义的变量。因为主函数也是一
个函数,它与其它函数是平行关系。
(2)形参变量是属于被调函数的局部变量,实参变
量是属于主调函数的局部变量。
(3)允许在不同的函数中使用相同的变量名,它们
代表不同的对象,分配不同的单元,互不干扰,
也不会发生混淆。如在例5.10中,形参和实参的
变量名都为n,是完全允许的。
2012-6-2151
(4)在复合语句中也可定义变量,其作用域只在复合语句
范隹I内。
例如:
main()
{/*s,a在该对花括号范围内有效*/
ints,a;
{/*b在该对花括号范围内有效7
intb;
s=a+b;
}
)
2012-6-2152
【例5.11】局部变量作用域举例。
#include<stdio.h>
intmain()
inti=1,j=2,k;/*4行,ij,k为main函数内定义的局部变量
k=i+j;
(
intk=5;/*第7行,k为复合语句内定义的局部变量*/
printf(,,k=%d\n,,,k);
)
,,,,
printf(i=%d,j=%d,k=%d\n,i,j,k);运行结果如下:
return0;
k=5
)i=1,j=2,k=3
2012-6-2153
2.全局变量
全局变量也称为外部变量,它是在函数外部
定义的变量。它不属于哪一个函数,它属
于一个源程序文件。其作用域是整个源程
序。在函数中使用全局变量,一般应作全
局变量说明。只有在函数内经过说明的全
局变量才能使用。全局变量的说明符为
externo但在一个函数之前定义的全局变量,
在该函数内使用可不再加以说明。
2012-6-2154
例如:
inta,b;/*a,b为全局变量*/
voidf1()
)
floatx,y;/*x,y为全局变量*/
intf2()
)
intmain()/*主函数*/
}
2012-6-2155
【例5.12】输入半径,求圆的面积和周长。
#include<stdio.h>
#definePI3.14
floatcircle;/*定义全局变量circle,用来获取周长*/
floatf(floatr)
intmain()
floats;
s=PI*r*r;floatr,area;
printf("\nPleaseinputr:");
circle=2*PI*r;
scanf("%f',&r);
returns;
area=f(r);
)printf("area=%f,len=%f\n",area,circle);
return0;
)
2012-6-2156
关于全局变量的使用,还需注意:
(1)全局变量可加强函数模块之间的数据联系,
但是又使函数要依赖这些变量,因而使得
函数的独立性降低。从模块化程序设计的
观点来看这是不利的,因此在不必要时尽
量不要使用全局变量。
(2)在同一源文件中,允许全局变量和局部变
量同名。在局部变量的作用域内,全局变
量不起作用。
2012-6-2157
【例5.13】全局变量和局部变量同名举例。
include<stdio.h>
inta=1,b=2;/*全局变量a,b*/
intsum(intx,inty)
(intmain()
intz;
(
z=x+y;inta=5;/*局部变量a*/
returnz;printf("a+b=%d,,,sum(a,b));
)return0;
}
运行结果如下:
a+b=7
2012-6-2158
5.7,2变量的存储类型
1.动态存储方式与静态存储方式
在C语言中,变量不仅具有确定的数据类型要求,
而且还有存储类型的要求。变量的存储类型是其
存储属性,即变量在内存中的存储方式,不同的
存储方式,将影响变量值的存在时间(即生存
期)。变量的存储方式可分为“静态存储”和
“动态存储”两种。
静态存储方式:指在变量定义时就分定存储单元并
一直保持不变,直至整个程序结束。
动态存储方式:指在程序执行过程中,使用它时才
分配存储单元,使用完毕立即释放。
2012-6-2159
用户存储空间可以分为三个部分:程序区、静态存
储区、动态存储区。
全局变量全部放在静态存储区,在程序开始执行时
给全局变量分配存储区,程序执行完毕就释放。
动态存储区存放以下数据:
(1)函数的形式参数;
(2)自动变量(未加static声明的局部变量)
(3)函数调用时的现场保护和返回地址。
这些数据在函数开始调用时分配动态存储空间,函
数结束时释放这些空间。
2012-6-2160
因此,在C语言中,每个变量有两个属性:数据类型和数据
的存储类型。一个变量说明的完整形式应为:
存储类型标识符数据类型标识符变量名,变量名…;
在c语言中,对变量的存储类型说明有以下四种:
auto自动变量
register寄存器变量
extern外部变量
static静态变量
例如:
staticinta,b;说明a,b为静态类型变量
autocharc1,c2;说明c1,c2为自动字符变量
staticinta[5]={123,4,5};说明a为静态整型数组
externintx,y;而明x,y为外部整型变量_
2012-6-2161
2.四种存储类型
(1)auto变量
函数中的形参利在函数内定义的未加存储类型标
识符的局部变量(包括在复合语句中定义的变量)
均视为自动变量,也就是说自动变量反省去说明
符aut。。在调用函数时系统将给自动变量分配存
储空间,函数调用结束时就自动释放空间。例如:
intf(intx)
inty;
autointz;
)
形参x和局部变量y、z都是自动变量。
2012-6-2162
(2)用static声明局部变量
若希望函数中的局部变量的值在函数调用结束后不消失而
保留原值,这时就应该指定局部变量为“静态局部变量”
用关键字static进行声明。
说明:
①静态局部变量属于静态存储类别,在静态存储区内分配存
储单元。在程序整个运行期间都不释放。而自动变量(即
动态局部变量)属于动态存储类别,占动态存储空间,函
数调用结束后即释放。
②静态局部变量在编译时赋初值,即只赋初值一次;而对自
动变量赋初值是在函数调用时进行,每调用一次函数重新
赋一次初值,相当于执行一次赋值语句。
③如果在定义局部变量时不赋初值的话,则对静态局部变量
来说,编译时自动赋初值0(对数值型变量)或空字符
(对字符变量)。而对自动变量来说,如果不赋初值则它
的值是一个不确定的值。
2012-6-2163
【例5.14】打印1到4的阶乘值。
#include<stdio.h>
intfac(intn)
(
staticintf=1;
f=f*n;
returnf;
}
intmain()
(
inti;
for(i=1;i<=4;i++)
printf("%d!=%d\n",i,fac(i));
return0;
}_.................
2012-6-2164
(3)register变量
为了提高效率,C语言允许将局部变量的值放在
CPU中的寄存器中,这种变量叫“寄存器变量”,
用关键字register作声明。
说明:
①只有局部自动变量和形式参数可以作为寄存器变
量;
②一个计算机系统中的寄存器数目有限,不能定义
任意多个寄存器变量;
③局部静态变量不能定义为寄存器变量。
2012-6-2165
【例5.15】使用寄存器变量。
intfac(intn)
(
registerinti,f=1;
for(i=1;i<=n;i++)
f=f*i
returnf;
)
intmain()
(
inti;
for(i=0;i<=4;i++)
printf("%d!=%d\n",i,fac(i));
return0;
)
2012-6-2166
(4)用extern声明全局变量
全局变量是在函数的外部定义的,它的作用域为从
变量定义处开始,到本程序文件的末尾。如果全局
变量不在文件的开头定义,其有效的作用范围只限
于定义处到文件结束。如果在定义位置之前的函数
要引用该全局变量,则应该在引用之前用关键字
extern对该变量作“全局变量声明”。表示该变量
是一个已经定义的全局变量。有了此声明,就可以
从“声明”处起,合法地使用该外部变量。
2012-6-2167
【例5.16】
#include<stdio.h>
intsum(intx,inty)
intz;
运行结果如下:
z=x+y;
returnz;30
}
intmain()
externA,B;
printf("%d\n",sum(A,B));
return0;
}
intA=10,B=20;
2012-6-2168
5.8综合实例
【例5.17】通过键盘输入10个整数,求最大
值和最小值及平均值。
方法1:将10个整数放在一个数组中,作为一个
整体来处理。分别用三个函数来求最大值、最小
值、平均值。
2012-6-2169
#include<stdio.h>
#defineN10
intmax(inta[],intn);
intmin(inta[],intn);
floatave(inta[],intn);
intmain()
inta[N],i,max_a,min_a;
floatave_a;
printf("Pleaseinput10integer:");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
max_a=max(a,N);
min_a=min(a,N);
ave_a=ave(a,N);
printf("Themaxis:%d\n",max_a);
printf("Theminis:%d\n",min_a);
printf("Theaverageis:%f\nn,ave_a);
2012-6-2170
rn
intmax(inta[],intn)
intmin(inta[],intn)
inti,m;
inti,m;
m=a[0];
m=a[0];
for(i=1;i<n;i++)
for(i=1;i<n;i++)
if(m<a[i])m=a[i];
if(m>a[i])m=a[i];
returnm;
returnm;
)
)
floatave(inta[],intn)
inti;
floatm=0;
for(i=0;i<n;i++)
m+=a
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年电动音乐车轮项目可行性研究报告
- 2025年玲珑锅项目可行性研究报告
- 2025年玫瑰豆沙项目可行性研究报告
- 2025年熔金钳项目可行性研究报告
- 湖南省邵阳市城区市级名校2024-2025学年初三4月第二次模拟考试英语试题含答案
- 上海市华师大二附中2024-2025学年高三生物试题理第三次调研考试试题解析含解析
- 衢州市重点中学2024-2025学年高三5月模拟考试自选试题含解析
- 新疆科技学院《列车运行控制技术》2023-2024学年第二学期期末试卷
- 2025春新版一年级下册语文.课文重点知识归纳
- 长春工程学院《微生物与生化药学专论》2023-2024学年第二学期期末试卷
- 某地块土壤污染状况调查汇报PPT模板框架
- 术前停药指南
- 居家养老服务规范:服务满意度测评
- 拉动式生产方案-课件
- 新能源汽车充电桩项目可行性报告
- 水资源利用知到章节答案智慧树2023年西安理工大学
- 静脉给药错误演练脚本
- IE动作MOD法培训资料
- 一汽解放维修手册说明书
- 禽流感人流感人间禽流感培训课件
- MT 191-1989煤矿井下用橡胶管安全性能检验规范
评论
0/150
提交评论