已阅读5页,还剩80页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1,第5章 函数,C 语言程序设计,大连理工大学出版社,第5章 函数,5.1 函数的作用 5.2 函数定义和函数调用 5.3 函数调用中的参数传递 5.4 函数的嵌套调用和递归调用 5.5 变量的作用域和存储类别 本章小结,2,2019/6/8,3,5.1 函数的作用, 程序结构清晰,可读性好。 减少重复编码的工作量。 可多人共同编制一个大程序,缩短程序设计周期,提高程序设计和调试的效率。,使用函数的 好处,2019/6/8,4,例5.1 函数调用的简单例子。,void myprint() int i=0; for (i=1; i=18; i+) printf(“*“); printf(“n”); ,void myprint_n(int n) int i = 0; for(i=1; i=n; i+) printf(“*“); printf(“n”); ,void main() myprint(); myprint_n(6); myprint_n(12); myprint(); ,程序的执行总是 从main函数开始,2019/6/8,程序运行情况如下: * * * *,5,例5.2 从键盘输入x和y的值,计算 xy的值(设y为整型量)。,算法一:调用C 语言中的库函数pow,计算 xy的值。 #include #include void main() double x = 0, z = 0; int y = 0; printf(“Input data: “); scanf(“%lf%d“, ,程序运行情况如下: Input data: 2 3 2.000000,3,8.000000,2019/6/8,6,算法二:自定义函数mypow,计算xy的值。 #include double mypow(double x, int y) int i = 0; double z = 1.0; for(i=1; i=y; i+) z = z * x; return z; void main( ) /* 主函数 */ double x = 0, z = 0; int y = 0; printf(“Input data: “); scanf(“%lf%d“, ,2019/6/8,7,从以上两个例子可以看到:,(1)一个C语言程序是由一个或多个函数组成,但必须有且只有一个main函数。 (2)main函数可以调用其他任何一个函数,而其他函数不能调用main函数,其他函数之间可以相互调用。 (3) C语言中不能在一个函数内部定义另外一个函数,即 C语言不允许函数嵌套定义。 (4) 函数有两种:一种是标准库函数。 另一种是自定义函数,main函数也是自定义函数。自定义函数需要用户设计编写,必须先定义后使用。,2019/6/8,8,5.2 函数定义和函数调用,1.函数定义的一般形式,函数类型 函数名(类型名 形式参数1, ) 声明部分 执行部分 ,例如:求两个数的最大值。 int max(int x,int y) int z; z = x y ? x : y; return( z ); ,类型省略时默认为int类型,函数的首部,函数体,2019/6/8,9,2. 无参函数的定义形式,函数类型 函数名( ) 声明部分 执行部分 ,例如: void hello( ) printf(“Hello,everyone!n “); main( ) hello( ); ,2019/6/8,圆括号需保留,形参表为空,10,3. 有参函数的定义形式,函数类型 函数名(形式参数表) 声明部分 执行部分 ,2019/6/8,形参必须是变量,11,例5.3 求三个整数中的最大值。,int mymax(int a,int b,int c) int max; if ( a b ) max = a; else max = b; if ( max c ) max = c; return (max); ,void main() int z, m, n, y; printf(“Input three number:n“); scanf(“%d %d %d“, ,2019/6/8,12,4. 空函数的定义形式,函数类型 函数名( ) ,程序设计中常在准备扩充功能的地方写上一个空函数,例如: void kongf() 用空函数先占一个位置,表明“这里有一个函数”,等以后扩充程序功能时,再将函数编好补充上。,2019/6/8,13,函数名(实参表列),在C语言中,把函数调用也作为一个表达式。因此凡是表达式可以出现的地方都可以出现函数调用。例如: 函数语句:welcome( ); 函数表达式: c=2*max(a,b); 函数参数:m=max(c,max(a,b);,5.2.2函数的调用,函数调用的一般形式:,2019/6/8,14,说明:,(1)函数名为被调用函数的函数名。 (2)如果被调函数是有参函数,在函数调用中应包含实际参数表(简称实参表)。实参应与被调函数中的形参个数相同、位置对应、类型一致。 (3)如果被调函数是无参函数,实参表为空,但一对圆括号不能省略。 (4)函数调用的执行过程: 首先实参与形参结合(即将实参的值赋给形参),然后程序执行流程转入被调函数的函数体中,执行函数体中的语句,函数体执行完之后,执行流程再返回到主调函数中调用语句的下一语句去执行。,2019/6/8,15,例5.4 调用函数,求 和n! ,其中 n 0 。,#include #include long myfac(int n) int i = 0; long y = 1; for(i = 1; i = n; i+) y = y * i; return y; ,void main() int n = 0; float y = 0; long z = 0; printf(“Input data:“); scanf(“%d“, ,程序运行情况如下: Input data:4 4:2.000000 4! = 24,2019/6/8,16,2. 函数调用的方式,从函数调用在程序中出现的位置看,函数调用可以分为三种方式: (1) 函数语句方式 myprint(); myprint_n(6); (2) 函数表达式方式 例如: z = 2 * myfac(n);,2019/6/8,17,(3) 函数参数方式 例如: m=min(a,min(b,c); 在这个赋值语句中,min(b,c)是一次函数 调用,它作为min函数的另一次调用的实 参。m的值是a、b、c三者中的最小者。 又如: printf(“ %f “,min(a,b); 也是把min(a,b)作为printf函数的一个实参 进行函数调用的。,2019/6/8,18,3. 形式参数和实际参数,例5.5 求两个整数中的大者。要求编写一个子函数求大者,在主函数中输入这两个整数并输出大者。,int max(int x, int y) int z; z = x y ? x : y; return(z); ,void main() int a, b, c; scanf(“%d,%d“, ,程序运行情况如下: 5,18 max is 18,x:,y:,b:,a:,18,5,5,18,z:18,2019/6/8,19,关于形参和实参的说明:, 函数未被调用时,形参并不占内存中的存储单元。只有在发生函数调用时,形参才由系统分配存储单元(与实参单元是不同的单元),并将实参值传递到形参单元中; 在执行被调函数的过程中,形参单元被访问或被重新赋值,但均与实参单元无关; 函数调用结束后,形参单元被系统释放,而实参单元仍然保留且值不变。在实参与形参之间传递数据采用的是单向的“值传递”方式。,2019/6/8,20, 实参可以是常量、变量或表达式。 例如: max(a+b,8); 实参的类型与相对应的形参的类型应相同或赋值兼容。如果实参为实型而形参为整型,或者相反,则按不同类型数值的赋值规则进行转换。假如,调用子函数max时,实参a的值为5.9,而形参x为整型,则系统会将实数5.9转换成整数5后传递给形参x。,2019/6/8,21,4. 函数的返回值, return 语句的两个功能: (1) 返回值。 (2)终止被调函数的执行,使流程返回主调函数。,return (表达式);,return 语句的语法格式如下:,2019/6/8,22, return 语句的使用形式: return 后面的表达式,可用圆括号也可不用。 例如: return(c); 与return c; 是等价的。 return(a b ? a : b); 与return a b ? a : b; 是等价的。 一个函数若没有返回值时,return 后面不带表达式,即: return; 如果不需要从被调函数带回函数值,则被调函数中可以不要return语句。,2019/6/8,23,一个函数可以有多个return语句,即多个出口。 例如: int sign(float x) if(x 0) return(1); else if(x = 0) return(0); else return(-1); ,2019/6/8,24,2)函数的返回值类型,函数的类型决定函数返回值的类型。 例如,下面是3个函数定义中的函数首部: int max(float x,float y) /* 函数值为整型 */ char let(char c1,char c2) /* 函数值为字符型 */ float min(int x,int y) /* 函数值为浮点型 */ 函数返回值类型一般应和return语句中的表达式类型一致,否则以函数的类型为准。,2019/6/8,25,例5.6 求两个整数中的大者。,int max(float x,float y) /* 定义函数为整型 */ float z; /* 定义变量z为单精度型 */ z = x y ? x :y; return(z); /* 将z值作为函数值返回 */ void main() float a,b; int c; scanf(“%f,%f“, ,程序运行情况如下: 6.5, 8.5 max is 8,2019/6/8,26, 对于无返回值的函数,函数的类型最好说明为void型,它表示“无类型”或“空类型”。若无返回值的函数省略void,函数将返回一个不确定的值。 这时在被调用函数的函数体中可以没有return语句,也可以有不带返回值的return语句,2019/6/8,27,例5.7 打印n个“#”的函数。 void spc(int n) 或: int i; for(i = 0; i n; i+) printf(“%c“, #); return; ,void spc(int n) int i; for(i = 0; i n; i+) printf(“%c“,#); ,无返回值的函数中使用return语句的示例:,main() spc(5); ,main() spc(5); ,2019/6/8,28,C语言规定,一般要求被调用函数定义在 前、调用在后。 若被调用函数定义在后、调用在前,可以 运用函数原型声明语句来解决这个问题。,2019/6/8,29,5. 被调函数声明与函数原型,格式1:类型名 函数名(参数类型1 参数名1, 参数类型2 参数名2,参数类型n 参数名n); 格式2:类型名 函数名(参数类型1,参数类型 2,参数类型n);,例如: void print(int mumber,char sex,float score); 大体上可猜出这是一个输出学号、性别和成绩的函数,而若写成: void print(int,float,char); 则无从知道参数的含义。,2019/6/8,30,例5.8 对被调函数的声明。,void main() float sub(float x, float y); /* 对被调函数sub的声明 */ float a, b,c; scanf(“%f,%f“, ,程序运行情况如下: 3.6,6.5 sub is -2.900000,2019/6/8,31,(3) 如果在文件的开头(在所有函数之前)对本文件中要调用的所有函数进行了声明,则在各函数中不必对其所要调用的函数再作声明。,char letterf (char,char); float floatf (float,float); int integerf(int,int); void main() /* 调用letterf、floatf和integerf 函数 */ /* 不必对它所调用的函数进行声明 */ char letterf(char cl,char c2) float floatf (float,float) int integerf(int,int) ,2019/6/8,注意区分函数声明和函数定义(不是一回事): 函数定义:对函数功能的确立,是一个完整的,独立的函数单位; 函数声明:旨在把函数的名字、函数类型以及形参的类型、个数和顺序通知编译系统,不包含函数体。 例:函数定义 函数声明,void myprint() int i=0; for (i=1; i=18; i+) printf(“*“); printf(“n”); ,float sub(float x, float y);,char letterf (char,char); float floatf (float,float);,33,5.3 函数调用中的参数传递,根据参数值类型的不同,“值传递”又分为 “数值传递”和“地址传递”两种类型。,5.3.1 简单变量作函数参数,当形参是简单变量时,实参与形参之间采用 “数值传递”方式。实现实参单元向形参单元 的单向传递。,2019/6/8,34,例5.9 编一程序,将一整数乘以10后 显示出来。,int mult(int n) n *= 10; /* 形参n的值被改变 */ return(n); void main() int number; int result; number = 668; result = mult(number);/* 以实参number去调用mult函数 */ printf(“number = %dn”,number); /* 实参number的值不会 printf(“result = %dn“,result); 被改变 */ ,程序运行结果为: number = 668 result = 6680,number:,n:,668,668,6680,2019/6/8,35,例5.10 输出Fibonacci数列的前17项。,int fib(int a, int b) int c; c = a + b; a = b; b = c; return c; void main( ) int i, first = 0, second = 1; printf(“%3d%3d“, first, second); for(i = 1; i = 15; i+) printf(“%3d“, fib(first, second); printf( “n“); ,程序运行结果为: 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1,a:,b:,c:,0,1,1,a:,first:,0,second:,1,i:,1,2019/6/8,形参a,b的值对实参first,second没有影响,36,5.3.2 数组作函数参数,1.数组元素作函数参数 同简单变量作函数参数的情形完全一样,单 个数组元素也可以作函数参数,也同样采用“数 值传递”方式。,2019/6/8,37,例5.11 在主函数中输入100个数,并调 用库函数求其中正数的算术平方根的和。,#include #include void main( ) float a100,sum = 0; int i; for(i = 0; i 0) sum = sum + sqrt(ai); printf(“%sum=%fn“,sum); ,2019/6/8,38,例5.12 有数组a和b,各含有10个元素,将它们对应地逐个比较( 即a0与b0比,a1与b1比, )。如果a数组中的元素大于b数组中的对应元素的数目多于b数组中元素大于a数组中对应元素的数目,则认为a数组大于b数组,并分别统计出两个数组对应元素大于、等于和小于的次数。,a: 14 2 3 4 5 6 7 8 9 10,b: 11 5 7 2 3 6 8 4 1 9,n:,k:,m:,2019/6/8,39,large(int x, int y) /* 将1或-1或 0返回主函数 */ int flag; if(x y) flag = 1; else if(x y) flag = -1; else flag = 0; return (flag); ,2019/6/8,40,void main() int large(int x, int y); int a10, b10, i, n=0, m=0, k=0; for(i = 0; i 10; i+) scanf(“%d“, ,printf(“%d %d %d “, n, m, k); if(n k) printf(“array a is larger than array b n “); else if(n k) printf(“array a is smaller than array bn“); else printf(“array a is equal to array b n “); /* n记录a比b大的元素个数 k记录a比b小的元素个数 m记录a与b相等的元素个数*/,2019/6/8,41,2.数组名作函数参数,数组名表示数组在内存中的起始地址。 例如:数组a在内存中从2000地址开始存放,则a的值为2000。2000是地址值,是指针类型的数据(第7中将介绍指针类型),不能把它看成是整型或其他类型数据。 实参是数组名,形参也应定义为数组形式,形参数组的长度可以省略,但 不能省,否则就不是数组形式了。 实参与形参采用“地址传递”方式,形参与实参占用同一存储区域,int a3=1,2,3;,2000,2019/6/8,42,(1) 一维数组名作为函数参数,以下4种情形是等效的: 实参和形参都是数组名; 实参为指向数组的指针变量,形参为数组名; 实参为数组名,形参为指向数组的指针变量; 实参和形参都是指向数组的指针变量。,2019/6/8,43,实参数组名代表一个已分配存储单元的数组的地址,实质上是一个指针常量,因此,无论用数组名还是用指向数组的指针变量作为实参,向形参传递的均是数组的地址。 形参是接收从实参传递过来的数组地址的,形参应该是一个指针变量。实际上,C编译就是把形参数组名作为指针变量来处理的。,2019/6/8,44,例5.13 一维数组名作为函数参数的情形。,#define N 9 void output(int a ,int n) int i; for(i=0;in; i+) printf(“%5d“,ai); printf(“n“); ,void main() int xN,i; for(i=0;iN;i+) xi=2*i; output(x,N); /函数调用 ,实参x,形参a,x0,x1,x2,x3,x4,x5,x6,x7,x8,a0,a1,a2,a3,a4,a5,a6,a7,a8,2019/6/8,45,例5.14 编写函数统计一个一维数组 (10个元素)中非0元素的个数。,int solve(int b ,int n) int sum=0,i; for(i = 0;i n;i+) if(bi!= 0) sum+; return(sum); ,void main() int a10,num,i; for(i = 0;i 10;i+) scanf(“%d“, ,实参a,形参b,a0,a1,a2,a3,a4,a5,a6,a7,a8,b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,a9,2019/6/8,46,例5.15 编一函数实现数组逆置。,数组逆置是将数组的第一个元素值放到最后一个 位置,第二个元素值放到倒数第二个位置, 直到最后一个元素值放到第一个位置。 (数组有个元素),a: 0 1 2 3 4 5 6 7 8 9,a: 9 8 7 6 5 4 3 2 1 0,a0=0,an=N-1,2019/6/8,47,#define N 9 void main( ) void fun(int aN); int aN,i; for(i=0;iN;i+) scanf(“%d“, ,void fun(int xN) int a0,an,temp; a0=0; an=N-1; while(a0an) temp=xa0; xa0=xan; xan=temp; a0+; an-; return; ,2019/6/8,48,(2)多维数组名作为函数参数,多维数组名作函数参数时,被调函数中对形参 数组的定义中,可以指定每一维的长度,也可以 不指定第一维的长度,但其余各维的长度都必须 指定。如: check(float a 10,int n) ,下面的参数说明都是不正确的: float a ; 或: float a10 ;,2019/6/8,49,例5.16 从键盘为一个5x5整型数组输入数 据,找出并显示主对角线上元素的最小值。,int small(int a55) int i,vm; vm = a00; for(i =1;i aii) vm = aii; return(vm); ,void main() int i,j,vmin; int array55; for(i = 0;i 5;i+) for(j = 0;j 5;j+) scanf(“%d“, ,2019/6/8,50,例5.17 有一个3x4的矩阵,设计函数求 该矩阵所有元素中的最大值。,void main( ) int max_value(int array 4); int a34=1,3,5,7,2,4,6,8,15,17,34,12; printf(“max value is %dn“,max_value(a) ); int max_value(int array 4) int i,j,max; max = array00; for(i = 0;i max) max=arrayij; return(max); ,a34:,array34:,2019/6/8,51,有关数组名作函数参数的进一步说明: 用数组名作函数参数,应该在主调函数和被调函数中分别定义数组。 实参数组与形参数组类型应一致,如不一致,结果将出错。 在被调函数如max_value() 中说明形参数组的大小,实则不起作用,实参数组只传给形参首地址.,2019/6/8,52,(3) 字符数组作函数参数,字符数组作参数时,传递的也是数组的地 址,即字符串的首地址,于是形参字符串和 实参字符串占用同一存储区域。,2019/6/8,53,例5.18 编一字符串连接函数,将任意 的两个字符串连接成一个字符串。,void connect_str(char s150,char s220) int i=0,j=0; while(s1i != 0) i+; printf(“n i = %dn“,i); while(s1i+=s2j+) != 0); void main( ) char str150,str220; int i,j; scanf(“%s“,str1); scanf(“%s“,str2); connect_str(str1,str2); printf(“n %s“,str1); ,程序运行情况如下: 1234567 89ABCDEF i = 7 123456789ABCDEF,2019/6/8,54,例5.19 编写一个求字符串长度函数, 并调用该函数,验证其正确性。,int stringlen(char s ) int i=0,len=0; while(si != 0) len+; i+; return len; ,void main() int stringlenth; char str =“I love China! “; stringlenth=stringlen(str); printf(“%4dn“,stringlenth); ,3,1,8,9,10,11,12,13,14,2,4,5,6,7,i:,3,1,8,9,10,11,12,13,2,4,5,6,7,0,2019/6/8,55,5.4 函数的嵌套调用和递归调用,5.4.1 函数的嵌套调用 C语言不允许函数嵌套定义,但是允许 函数嵌套调用,即允许在调用一个函数的过 程中,又调用另一个函数。,2019/6/8,56,例5.20 求三个数中最大数和最小数 的差值。,int dif(int x, int y, int z); int max(int x, int y, int z); int min(int x, int y, int z); void main() int a, b, c, d; scanf(“%d%d%d“, ,程序运行情况如下: Input Data:15 20 12 Max - Min= 8,int max(int x, int y, int z) int r1,r2; r1 = (x y) ? x: y; r2 = (r1 z) ? r1: z; return(r2); int min(int x, int y, int z) int r; r = (x y) ? x: y; return(r z ? r: z); ,2019/6/8,57,5.4.2 函数的递归调用,函数的递归调用是指在调用一个函数的 过程中,又出现直接或间接地调用该函数本 身的情形。 直接调用函数本身的称为直接递归调用。 间接地调用函数本身的称为间接递归调用。,2019/6/8,58,(1)直接递归调用示意。,float func(int n) int m; float f; f = func(m); 在调用函数func的过程中,又要调用func函 数,这种调用是直接递归调用。,void main() float x,k=5; x=func(k); printf(“%f”,x); ,2019/6/8,59,(2) 间接递归调用示意。,func1(int n) func2(int x) int y; int m; func2(y); func1(m); 在调用funcl函数的过程中,要调用func2函数, 而在执行函数func2过程中又要调用funcl 函数, 这样形成的就是间接递归调用。,2019/6/8,60,递归的特别之处在于递归分解的子问题与 原问题具有相同性质和相同的表现形式,但 是子问题比原问题规模小了,变得简单了。 采用递归方法处理问题的关键是: 一、找出求解的递归公式 二、确定递归结束条件,2019/6/8,61,例5.21 用递归方法求n!(n为非负整数)。,分析:假设n=5,则: 5! = 5 * 4! 4! = 4 * 3! 3! = 3 * 2! 2! = 2 * 1! 1! = 1 0! = 1,可用如下递归公式表述:,fac(n)=,n*fac(n-1) (n1),1 (n=0,1),递归结束 条件,2019/6/8,62,递归调用过程(求4!),2019/6/8,63,float fac(int n) float f; if(n=0|n=1) f = 1; else f = n * fac(n-1); return(f); ,void main() int n; float y; scanf(“%d“, ,程序运行情况如下: 10 10!= 3628800,递归结束条件,递归调用,2019/6/8,64,例5.22 有5个人坐在一起,问第5个人多少岁? 他 说比第4个人大2岁;问第4个人岁数,他说比第3 个人大2岁;问第3个人,又说比第2个人大2岁; 问第2个人,说比第1个人大2岁;最后问第1个 人,他说他10岁。请问第5个人多少岁?,分析:每一个人的年龄都比其前一个人的年龄大2岁,显然这是一个递归问题。即: age(5)=age(4)+2 age(4)=age(3)+2 age(3)=age(2)+2 age(2)=age(1)+2 age(1)=l0,age(n-1)+2 (n1),10 (n=1),递归结束 条件,age(n),2019/6/8,65,int age(int n) int c; if (n = 1) c = 10; else c=age(n - 1) + 2; return(c); void main() printf(“%d n“,age(5); ,运行结果如下: 18,2019/6/8,66,例5.23 用递归方法求解斐波纳契 (Fibonacci)数列。,0,1,1,2,3,5,8,13,21,34,为 斐波纳契数列。从中可以看出,斐波纳契数 列第n项的值是其前两项的和,这就是递归 公式;而当n=0和1时,斐波纳契数列项就 是n值本身,这就是递归结束条件。 可用如下递归公式表述:,fib(n-1)+fib(n-2) (n2),0 (n=0),递归结束 条件,fib(n),1 (n=1或n=2),2019/6/8,67,void main() int fib(int n); /*函数声明*/ int i; for (i = 0; i 20; i+) /*求斐波纳契数列前20项*/ if (i%5=0) printf(“n“); printf(“%12d“,fib(i); /*输出斐波纳契数列第i项的值*/ printf(“n“); int fib(int n) /*定义求斐波那契数列第n项值的函数*/ if(n = 0 | n = 1) /*递归结束条件*/ return n; else return fib(n - 2)+fib(n - 1); /*递归调用*/ ,2019/6/8,68,程序运行结果如下: 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181,2019/6/8,5.5 变量的作用域和存储类别,所谓变量的作用域,是指变量在程序中的有效范围。如果一个程序只由一个main函数组成,其变量的作用域情况比较简单,显然其变量只在main函数中有效。但是一般一个 C 程序都包含多个函数,那么定义在 A 函数中的变量可否在 B 函数中使用?这涉及变量的作用域问题。从作用域角度,变量分为局部变量和全局变量。 所谓变量的存储类别,是指变量在内存中的存储方法。通常 C 语言程序在计算机内占用的存储空间可分为 3 部分,分别被称之为程序区、静态存储区、动态存储区。其中,程序区中存放的是可执行程序的机器指令,静态存储区中存放的是需要占用固定存储单元的变量,动态存储区中存放的是不需要占用固定存储单元的变量。不同的存储方法将影响变量值的存在时间(即生存期)。从存储类别角度,变量有动态存储和静态存储两种类型。,69,2019/6/8,5.5.1 局部变量及其存储类型,在函数内部定义的变量称为局部变量,局部变量的作用域仅仅局限于定义它的函数。 例如: char func1(int a, char s1, char s2) /* 函数func1 */ int b,c; /* a、s1、s2、b、c有效 */ float func2(float m, float n, int a ) /* 函数func2 */ float x, y, z; /* m、n、a、x、y、z有效 */ int b, c; /* b、c有效 */ ,70,2019/6/8,5.5.1 局部变量及其存储类型,局部变量有3 种存储类型:自动类(auto)、静态类(smtie)和寄存器类(register)。 1.自动类变量 在函数内定义的变量,如果不显式地指定其存储类型,系统会将其默认为自动类变量。在定义自动类变量时,应该在定义变量的类型名前面使用auto关键字,如: auto float f; auto是C语言编译系统默认的存储类型,所以关键字auto可以省略。 自动类变量是在动态存储区内分配单元的(因而也称其为动态变量),函数返回时,编译系统将释放这些存储单元,即当函数调用结束时,自动类变量不复存在。,71,2019/6/8,例5.24 编一程序,每调用一次函数,显示一次自动变量中的内容,然后给其值加1。,#include void test_auto() int v = 0; printf(“ v =%dn“,v); + v; void main() int i; for(i = 0;i 4;i+) test_auto(); ,72,程序运行情况如下: v =0 v =0 v =0 v =0,2019/6/8,5.5.1 局部变量及其存储类型,2.静态类变量 如果希望在函数调用结束后,仍然保留函数中定义的局部变量的值,则可以将该局部变量定义为静态局部变量。在定义静态局部变量时,应该在定义变量的类型名前面使用static关键字,如: static int x; 静态局部变量在静态存储区中分配存储单元,在整个程序运行期间都不释放,因此,每次函数调用结束后,它的值并不消失,其值能够保持连续性。 静态局部变量是在编译阶段赋初值的,且只赋一次初值,以后调用函数时不再赋初值,而是保留上一次函数调用时的结果。,73,2019/6/8,例5.25 编一程序,每调用一次函数,显示一次静态局部变量中的内容,然后给其值加1。,#include void test_static() static int v = 0; printf(“ v =%dn“,v); + v; void main( ) int i; for(i = 0;i 4;i+) test_static(); ,74,2019/6/8,程序运行情况如下: v =0 v =1 v =2 v =3,例5-26 使用自动存储变量和静态存储变量,#include int myfun(); /* 对函数myfun的声明 */ void main( ) int i=0,a=0; for(i = 1; i = 2; i+) a = myfun(); printf(“%4d“,a); int myfun() auto int x = 1; static int y = 1; x = x + 2; y = y + 2; return (x + y); ,程序运行情况如下 6 8,5.5.1 局部变量及其存储类型,3.寄存器变量 一般情况下,变量(包括静态存储方式和动态存储方式)的值是存放在内存中的。当程序中用到一个变量的值时,由控制器发出指令将内存中该变量值送到运算器中。经过运算器进行运算,如果需要存数,再从运算器将数据送到内存存放。如果有某些变量使用频繁,则存取这些变量的值要花不少时间。为提高执行效率,C语言允许将局部变量的值放在运算器里的寄存器中,需要用时直接从寄存器取出参加运算,不必再到内存中去存取,这样就可以提高执行效率。这种变量属于寄存器类变量,一般 称 之 为 寄存器变量,在定义寄存器变量时,应该在定义变量的类型名前面使用register关键字。,76,2019/6/8,例5.27 编写一个用register说明变量的程序。,#include void myprint(register int n) /* 形参n作为寄存器变量 */ while(n = 1) printf(“*“); n-; printf(“n“); void main( ) int a = 1000; myprint(a); 运行程序时输出1000个“*”。,77,2019/6/8,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026江苏省教育系统公开招聘考试(教育理论/公共知识)历年参考题库含答案详解
- 2026江苏住院医师规范化培训考试(检验科Ⅱ阶段)题库历年参考题库含答案详解
- 2026正高面审答辩-正高004面审答辩肾内科学历年题库含答案详解
- 2026文物保护工程从业资格考试(责任设计师·近现代重要史迹及代表性建筑)历年参考题库含答案详解
- 冰淇淋烹饪课程设计
- DCT图像压缩应用教程课程设计
- AI换脸特效剪辑课程设计
- 包装课程设计作业范文
- 图嵌入欺诈识别课程设计
- 机器学习垃圾邮件分类器系统设计课程设计
- 2025年全国HIV抗体诊断试剂临床质量评估报告范文
- 国际中文教师考试试题及答案
- 电锅炉-安装工艺
- 快递车辆承包协议书
- 拆除临时用电施工方案
- 《铁路调车工作》课件
- 《农业工程学》教材笔记
- 小班语言活动秋天的颜色
- 更换膨胀节施工方案
- 混凝土强度评定表(GB/T50107-2010)
- 履带吊安拆装方案-天宫庄园站
评论
0/150
提交评论