版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第六章第六章 函函 数数C6.1 概 述 函数是一段程序,它完成特定的任务,使用它时可用简单的方法为其提供必要的数据,然后自动执行这段程序,计算完毕后能保存计算结果回到程序原来的位置继续计算。C如果把编程比做制造一台机器,函数就好比其零部件 可将这些“零部件”单独设计、调试、测试好,用时拿出来装配,再总体调试 这些“零部件”可以是自己设计制造/别人设计制造/现在的标准产品 而且,许多“零部件”我们可以只知道需向它提供什么,它能产生什么,并不需要了解它是如何工作、如何设计制造的所谓“黑盒子”。黑箱(函数)结果(输出参数)输入参数C 函数用于把较大的计算任务分解成若干个较小的任务 使程序人员可以在
2、其他函数的基础上构造程序,而不需要从头做起 一个设计得当的函数可以把具体操作细节对程序中不需要知道它们的那些部分隐藏掉,从而使整个程序结构清楚,减轻了因修改程序所带来的麻烦。 C语言在设计函数时考虑了效率与易于使用这两个方面。一个C程序一般都由许多较小的函数组成,而不是只由几个比较大的函数组成。 一个程序可以驻留在一个文件中,也可以存放在多个文件中。各个文件可以单独编译并与库中已经编译过的函数装配在一起。C编写一个测试软件显示软件封面检查密码产生题目接受回答评判计分显示结果如果要继续练习告别词Cmain() char ans = y;clrscr();cover(); /*调用软件封面显示函数
3、*/password(); /*调用密码检查函数*/while (ans =y| ans =Y) question(); /*调用产生题目函数*/ answers(); /*调用接受回答函数*/ marks(); /*调用评分函数*/ results(); /*调用结果显示函数*/ printf(“是否继续练习?(Y/N)n”); ans=getchar (); printf(“谢谢使用,再见!”);C/*定义所用函数*/cover() /*软件封面显示函数*/password() /*密码检查函数*/question() /*产生题目函数*/answers() /*接受回答函数*/marks
4、() /*评分函数*/results() /*结果显示函数*/C在C程序设计中,通常: 将一个大程序分成几个子程序模块(自定义函数) 将常用功能做成标准模块(标准函数)放在函数库中供其他程序调用 将程序中反复使用的程序段写成函数的形式,某些只用一次的程序段往往也写成函数形式 引入函数的优点: 减少重复编写程序的工作量 使程序便于调试和阅读C例6.1 main( )/* 主函数 */ printstar( ); /*调用printstar函数画*/ print_message(); /*调用print _message函数写字*/ printstar( ); /*调用printstar函数画*/
5、 printstar( ); /*printstar函数*/ printf(“n*”);print_message( ); /* print_message函数*/ printf(“n Hello! ”);运行结果:* Hello!*C 程序的执行从main函数开始,由主函数调用其它函数,其它函数也可以相互调用,程序流程最后回到main函数,在main函数中结束整个程序的运行 所有函数在定义时都是平行的,相互独立(一个函数并不从属于另一个函数),即函数不能嵌套定义,但可以相互调用 一个程序可以由一个或多个源程序文件组成C 一个(主调)函数可以多次调用多个(被调)函数。同一个函数也可以被一个或多
6、个(主调)函数调用任意多次。下图说明一种调用关系:mainabcfdefghid函数分类使用情况库函数(标准函数):由系统提供,用户可以直接使用用户自定义函数:解决用户的专门需要函数形式无参函数:主调函数与被调函数之间没有数据传递有参函数:主调函数与被调函数之间有数据传递任务情况带返回值不带返回值C6.2 函数的定义 一般形式: 函数类型说明符 函数名(形式参数表) 变量说明部分 语句部分函数体含义:类型说明符:指定函数值的类型。若该项缺省,表示函数值为 int 型。若函数没有值,应写作void.C函数的定义 函数名:标识符,用于标识函数,并用其来调用函数。 函数名字有值,它代表函数的入口地址
7、。形式参数表:说明参数的个数和类型,简称形参表。一般来说,计算函数需要多少原始数据,函数的形参表中就有多少个形参,每个形参存放一个数据。变量说明:说明函数中用到的除形参以外的其它变量。函数体:为了完成特定的功能而设计的一个或多个语句。C函数的定义 无参函数的定义一般形式: 数据类型 函数名() 说明部分 语句现代风格是: 数据类型 函数名(void) 说明部分 语句例如: print_message( )C函数的定义 有参函数的定义一般形式: 数据类型 函数名(形参表) 形参类型说明; 说明部分 语句现代风格是: 数据类型 函数名(带类型形参表) 说明部分 语句Cint max(x,y)int
8、 x,y;int z;z=xy?x:y;return(z)数据类型 函数名(形参表)形参类型说明;说明部分语句int max(int x,int y)int z;z=xy?x:y;return(z)/*现代风格是:函数名(带类型形参表)*/C空函数一般形式: 数据类型 函数名() 例如:dummy( ) 特点 :调用后什么也不做用处:建立程序结构,该空函数在需要时补充 C例6.2 求两个整数中的大者并输出main() int a=2,b=25; int c; c=max(a,b); printf(“Max is %dn”,c);max(int x,int y) int z; z=xy?x:y;
9、 return z;运行输出:Max is 25C例6.3 求两个实数中的大者并输出main() float a=1.5,b=2.5; int c; c=max(a,b); printf(“Max is %dn”,c);max(float x,float y) float z; z=xy?x:y; return z;运行输出:Max is 2 (编译通过,结果错误)Cmain() float a=1.5,b=2.5; float c; c=max(a,b); printf(“Max is %fn”,c);max(float x,float y) float z; z=xy?x:y; retur
10、n z;将%d改为%f,将int c;改为float c; 运行输出:Max is 2.000000 (结果仍然错误)Cmain() float a=1.5,b=2.5; float c; c=max(a,b); printf(“Max is %fn”,c);float max(float x, float y) float z; z=xy?x:y; return z;将max(float x, float y)改为float max(float x, float y)编译出错C为什么?C6.3 函数的调用 函数定义制造函数函数使用声明(准备使用) 调用(使用函数)通过函数调用,两个函数中的数
11、据发生联系。C6.3.1 形式参数和实际参数形式参数:定义函数时函数名后括号内的变量名称实际参数:主调函数中调用函数时,函数名后括号内的参数(变量,表达式等)C例6.4 调用函数时的数据传递main() int a,b,c; scanf(%d,%d,&a,&b); c=max(a,b); printf(“Max is %dn”,c);max(x,y)int x,y;int z; z=xy?x:y; return z;实际参数形式参数a bx yC说明 形参在函数调用前不占用存储单元,在调用时被分配,调用后释放所占用的存储单元; 形参只能是变量,而实参可以是常量、变量或表达式,但
12、要求它们有确定的值。调用时将实参的值赋给形参。 在函数中必须指定形参的类型; 实参和形参个数相等,按顺序对应,一一传递,实参和形参的类型应相同或赋值兼容; 语言规定,实参对形参的数据传递是“值传递”,即单向传递,只由实参传给形参,而不能由形参传回来给实参。在内存中,实参单元与形参单元是不同的单元。void fun() int x=7; printf(i=%d, j=%d, x=%dn, i, j, x);main( ) int i=2, x=5, j=7; fun( ); printf(i=%d, j=%d, x=%dn, i, j, x);i=7, j=6, x=7i=2, j=7, x=5
13、#include void sum(int x, int y, int z) z=x+y;main( ) int a=1, b=2, c=0; sum( a, b, c ); printf(c=%dn, c);c=?0C6.3.2 函数的返回值函数的返回值是通过函数中的return语句获得的。return语句将被调用函数中的一个确定值带回主调函数中去。return语句一般形式: return(表达式); 或:return 表达式; 或:return;若return后面带表达式,首先计算表达式的值,表达式的值就是所求的函数值。表达式的类型与函数首部说明的类型一致。 max(int x, int
14、y) int z; z=(xy)?x:y; return( );return();一个函数可以含有多个return语句,但当执行到其中一个return语句就返回主调函数。一个函数可以没有return语句,此时当函数执行到最后一个界限符“”时返回主调函数。说明说明C 函数值的类型:应当在定义函数时指定函数的类型。 max(int x, int y) min(int x, int y) letter(char c1, char c2)max(int x, int y)int max(int x, int y)C 在定义函数时,对函数值声明的类型一般应该和return语句中的表达式类型一致;若不一致
15、,则以函数类型为准(自动转换)。 对于有返回值的函数,若return语句后面没有表达式,或没有return语句,此时带回一个不确定的返回值。 为了明确表示“不带回值”,可以用void定义“无类型”(或称“空类型”)。void stars(int n)Cprintstar()printf(*);main() int a; a=printstar(); printf(%d,a);例 函数带回不确定值输出:10void printstar() printf(*);main() int a; a=printstar(); printf(%d,a);编译错误!C例 函数返回值类型转换main() flo
16、at a,b; int c; scanf(%f %f,&a,&b); c=max(a,b); printf(Max is %dn,c);max(float x, float y) float z; z=xy?x:y; return(z);运行输出:1.5 2.5 Max is 2 C6.3.3 函数调用的一般形式 函数名(实参1,实参2,实参n)执行过程:计算各个表达式,得到值v1,vn,把v1,vn赋给对应的形参。然后转去执行函数体,函数体执行结束后,即遇到return语句或执行完函数的最后一个语句,返回到函数调用处。C说明 实参与形参 多个实参间用逗号隔开 实参与形参间个数
17、相等,类型应一致 实参与形参按顺序对应,一一传递数据 实参表求值的顺序与系统有关C调用方式: 函数语句:由函数调用加上分号构成,在主调函数中可作为一个独立的语句 stars(20); print_message( ); 函数表达式:函数调用作为一个运算对象出现在表达式中,此时要求函数带回一个确定的值以参加表达式的运算 c=max(a, b); 函数参数:函数调用作为另一个函数的实参,其值作为一个实际参数传给被调函数的形参进行处理;此时也要求函数带回一个确定值 m=max(a, max(b, c);C 调用位置首先被调用函数必须是已存在的函数,如用户自定义函数或库函数。如果使用库函数,需要在文件
18、的开头用#include 命令将需要的库函数包含到文件中。 #include 调用同一源文件中的非标准函数时,必须在主调函数中对所调函数进行声明: 函数声明语句(函数原型)C6.4 函数原型一般形式: 类型标识符 被调函数名(形参类型 形参名 );功能:通知编译程序函数值是什么类型,有多少参数及它们各自的类型,为编译程序进行类型检查提供依据例如: double power( int x, int n); 或 double power(x , n); 或 double power( );C例6.5main() float add(); float a, b, c; scanf(“ %f, %f”
19、, &a, &b); c=printf(“ sum is %f ”, add(a, b) ); float add (x, y) float x, y; float z; z=x+y; return (z); /*对被调用函数的说明*/作为表达式被调用/*定义add函数*/运行结果:C函数定义和函数声明的区别 函数的定义是确定函数的功能,包括函数名,函数值类型,形参及类型和函数体全部内容。 函数的声明只是对要被调用的函数的返回值的类型进行说明,它只包括函数名、函数类型或形参类型,不包括函数体。C三种情况下可以省略声明: 函数值是整型(int)或字符型(char)时系统自动按整型
20、说明; 所调函数的定义出现在主调函数之前时; 文件一开头,在所有函数之前,对所用函数作了声明 C无函数说明整型函数main( ) int a,b,c; scanf (“%d,%d”,&a,&b); c=max(a,b); printf(“Max is %d”,c); max( x,y) int x,y; int z; z=xy? x:y; return(z); 函数值是整型(int)或字符型(char)时系统自动按整型说明C被调函数在主调函数之前主调函数在被调函数之后被调用函数出现在主调用函数之前。 float add (float x, float y) float z; z
21、=x+y; return (z); main( ) float a, b; scanf( %f, %f,&a, &b); printf( sum is %f , add(a, b) ); C在所有函数之前说明函数类型此处不必说明定义letter函数文件一开头,对所用函数作了声明 char letter( ); main( ) . char letter (c1, c2) char c1,c2; . Cmain() float a=1.5,b=2.5; float c; c=max(a,b); printf(“Max is %fn”,c);max(float x,float y)
22、 float z; z=xy?x:y; return z;例6.3 求两个实数中的大者并输出运行输出:Max is 2.000000 (编译通过,结果错误)因为函数没声明!Cmain() float max(float x,float y); float a=1.5,b=2.5; float c; c=max(a,b); printf(“Max is %fn”,c);float max(float x,float y)float z; z=xy?x:y; return z;运行输出:Max is 2.500000 main() float max(float x,float y); float
23、 a=1.5,b=2.5; float c; c=max(a,b); printf(“Max is %fn”,c);float max(float x,float y)float z; z=xy?x:y; return z;函数原型C附:调用外部函数(其他源文件中定义的函数)时 函数说明语句 extern 函数名(); 例 文件中 main() int x=80,y=90,c; extern max(); /*函数说明*/ c=max(x,y)+20;/*调用max函数*/ printf(“Max is %dn”,c);文件中(与同目录)extern max(int a,int b) /*ex
24、tern可省略*/float c; c=ab?a:b; return c;C6.5 函数的嵌套调用 C语言允许嵌套调用函数,即在调用一个函数的过程中,又调用另一个函数主函数()声明a函数 调用a函数 a函数()声明b函数 调用b函数 b函数() C6.6 函数的递归调用 C语言允许递归调用函数,即在调用一个函数的过程中,又直接或间接的调用该函数本身直接递归调用 调用函数的过程中又调用该函数本身int f(int x)int y; y=f (x); return y;C间接递归调用 调用f1函数的过程中调用f2函数,而f2中又需要调用f1。显然,以上均为无终止递归调用。为此,一般要用if语句来控
25、制使递归过程到某一条件满足时结束。int f1(int x)int y; y=f2(x); return y;int f2(int x)int y; y=f1(x); return y;C递归法:类似于数学证明中的反推法,从后一结果与前一结果的关系中寻找其规律性。归纳法可以分为:递推法 从初值出发,归纳出新值与旧值间直到最后值为止存在的关系要求通过分析得到: 初值+递推公式编程:通过循环控制结构实现(循环的终值是最后值)递归法 从结果出发,归纳出后一结果与前一结果直到初值为止存在的关系要求通过分析得到: 初值+递归函数C编程:设计一个函数(递归函数),这个函数不断使用下一级值调用自身,直到结果
26、已知处选择控制结构其一般形式是:在主函数中用终值n调用递归函数,而在递归函数中:递归函数名f (参数x) if (n=初值) 结果=; else 结果=含f(x-1)的表达式; 返回结果(return);C例6.6 用递归法求n!递推法0!=1 1!=0!12!=1!2n!=(n1)!n分析得Sn=n!的求解 1 (n=1,0)Sn=Sn-1n (n1)其中Sn-1先求出递归法n!=(n1)! n(n1)!=(n2)!(n1)(n2)!=(n3)!(n2)2!=1!2分析得f(n)=n!的求解f(n)=f(n1)n (n1)其中f(n1)未求出C实际上,递归程序分两个阶段执行回推(调用):欲求
27、n! 先求 (n-1)! (n-2)! 1! 若1!已知,回推结束。(1) 递推(回代):知道1! 2! 可求出3! n ! main() int n; float s; float fac(); printf(Input n=); scanf(%d,&n); s=fac(n); printf(%d!=%.0f,n,s);float fac(int x)int f; if (x=0|x=1) f=1; else f=fac(x-1)*x; return f; 运行:Input n=55!=120C例6.7 有5个人,第5个人说他比第4个人大2岁,第4个人说他对第3个人大2岁,第3个人说
28、他比第2个人大2岁,第2个人说他比第1个人大2岁,第1个人说他10岁。求第5个人多少岁。分析: 10 (n=1) age(n)= age(n-1)+2 (n1)C图示C程序:main()clrscr(); printf(%d,age(5); age(int n) int c; if (n=1) c=10; else c=age(n-1)+2; return c;运行:18C 1 1 1 1 2 1 1 3 3 1 1 4 6 4 11 5 10 10 5 1 分析: 第x行有x个值 对第x行第y列,其值(不计左侧空格时) 1 (y=1 或 y=x)c(x,y)= c(x-1,y-1)+c(x-
29、1,y)例6.8在屏幕上显示杨辉三角形C程序如下:main()int i,j,n;clrscr();printf(Input n=);scanf(%d,&n);for (i=1;i=n;i+) for (j=0;j=n-i;j+) printf( ); for (j=1;j=i;j+) printf(%3d ,c(i,j); printf(n); int c(int x,int y)int z;if (y=1|y=x) return 1;else z=c(x-1,y-1)+c(x-1,y); return z; C#include rev() char c; c=getchar();
30、if (c=$) printf(%c,c); else rev(); printf(%c,c); main()rev();例6.9运行下列程序,当输入字符序列AB$CDE并回车时,程序的输出结果是什么?运行:$BAC例6.10反向输出一个整数(非数值问题)非数值问题的分析无法象数值问题那样能得出一个初值和递归函数式,但思路是相同的。分析方法:简化问题:设要输出的正整数只有一位,则“反向输出”问题可简化为输出一位整数。对大于10的正整数,逻辑上可分为两部分:个位上的数字和个位以前的全部数字。将个位以前的全部数字看成一个整体,则为了反向输出这个大于10的正整数,可按以下步骤: a、输出个位上的数字
31、; b、将个位除外的其他数字作为一个新的整数,重复a步骤的操作。C其中b问题只是对原问题在规模上进行了缩小递归。所以,可将反向输出一个正整数的算法归纳为: if (n为一位整数) 输出n; else 输出n的个位数字; 对剩余数字组成的新整数重复“反向输出”操作; C程序如下:#include void main() void printn(int x); int n; printf(Input n=); scanf(%d,&n); if (n=0&x%cn,getone,putone); void hanoi(int n,char one,char two,char thre
32、e) if(n=1) move(one,three); else hanoi(n-1,one,three,two);move(one,three);hanoi(n-1,two,one,three); main() int m; printf(Input the number of disks:); scanf(%d,&m); printf(The steps to moving %3d disks:n,m); hanoi(m,A,B,C); Input the number of disks: 3The steps to moving 3 disks:A-CA-BC-BA-CB-AB-
33、CA-CC递归的条件:1、须有完成函数任务的语句;long f(int n) long y; if (n=1) y=1; else y=n*f(n-1); return(y);2、一个确定是否能避免递归调用的测试;3、一个递归调用语句; 该语句的参数应该逐渐逼近结束条件,以至最后断绝递归。4、先测试,后递归调用。在递归函数定义中,必须先测试,后递归调用。也就是说,递归调用是有条件的,满足了条件后,才可以递归。long f(int n) long y; y=n*f(n-1); if (n=1) y=1; return(y);C递归的特点:1、递归调用不是重新复制该函数,每次调用它时,并以新的变量
34、重新开始执行;每次递归返回时,当前调用层的局部变量和形参被释放,并返回上次调用自身的地方继续执行;2、递归调用一般并不节省内存空间,因为每次调用都要产生一组新的局部变量,从而不破坏上层的局部变量;3、递归调用一般并不能加快程序的执行速度,因为每次调用都要保护上层局部量(现场),而返回时又要恢复上层局部量,占用执行时间;4、递归函数中,必须有结束递归的条件;5、递归调用的优点是能实现一些迭代算法难以解决的问题。C6.7 数组作为函数参数 数组元素可以作函数的实参 数组名可以作函数的实参和形参 多维数组可以作函数参数6.7.1 数组元素作函数的实参 由于表达式可以做实参,数组元素可以作为表达式的组
35、成部分,因此,数组元素可以做函数的实参,并且可以单向传递给形参。C例 两个数组大小比较432105a562312107688432105b212343986654n=0m=0k=0in=0m=0k=1in=0m=1k=1in=1m=1k=1in=1m=1k=2in=2m=1k=2in=3m=1k=2a和b为有10个元素的整型数组比较两数组对应元素变量n,m,k记录aibi, ai=bi, aik,认为数组ab 若nk,认为数组ab 若n=k,认为数组a=b#include main() printf(Enter array a:n); for(i=0;i10;i+)scanf(%d,&
36、ai); printf(Enter array b:n); for(i=0;i10;i+)scanf(%d,&bi); for(i=0;iy) flag=1; else if(xy) flag=-1; else flag=0; return(flag);C数组名作函数参数 地址传递 在主调函数与被调函数分别定义数组,且类型应一致 形参数组大小(多维数组第一维)可不指定 形参数组名是地址变量C例 求学生的平均成绩 #include float average(int stu10, int n); void main() int score10, i; float av; printf(I
37、nput 10 scores:n); for( i=0; i10; i+ ) scanf(%d, &scorei); av=average(score,10); printf(Average is:%.2f, av); float average(int stu10, int n) int i; float av,total=0; for( i=0; in; i+ ) total += stui; av = total/n; return av; 实参用数组名形参用数组定义, int stu .2109score562312.88stuC说明:1、float score10;aver=
38、average(score);float average(float array10)2、3、float average(float array , int n) aver=average(score, 10);CC例 数组元素与 数组名 作函数参数比较12a调用前a0a112a调用a0a112xy21xy交换12a返回#include void swap2(int x,int y) int z; z=x; x=y; y=z;main() int a2=1,2; swap2(a0,a1); printf(a0=%dna1=%dn,a0,a1);值传递C12a调用前12ax调用21ax交换21a
39、返回#include void swap2(int x) int z; z=x0; x0=x1; x1=z;main() int a2=1,2; swap2(a); printf(a0=%dna1=%dn,a0,a1);地址传递例 数组元素与 数组名 作函数参数比较C例6.12用选择法对数组中10个整数按由小到大排序所谓选择法就是:先将10个整数中最小的数与a0对换,再将a1到a9中最小的数与a1对换;.每比较一轮,找出未经排序的数中最小的一个,共应比较 9 轮。程序设计 函数sort(array, n) 对数组元素按由小到大排序 主程序 :输入array数组,调用 sort 函数比较,输出排
40、序后的array数组C排序函数:无返回值,数组名为形参形参数组说明可以不指定大小交换arrayj和 arrayi; void sort (int array , int n ) int v, j, t; for (i=0; in-1; i+) for (j=i+1; jn; j+) if (arrayjarrayi) t=arrayi; arrayi=arrayj; arrayj=t; Cmain ( ) int a10, i;printf(“enter array: n”);for (i=1; i10; i+) scanf (“ %d ”,&ai);sort(a, 10);print
41、f(“the sorted array: n”);for (i=1; i10; i+) printf (“ %4d ”, ai);printf(“n”);实参数组说明数组 a 赋值调用排序函数由于地址传递,实参数组 a 改变C多维数组作函数参数形参数组定义时可以指定每一维的大小,也可省略第一维的大小说明(但不能省略第二维及其它高维的大小说明)例如 : int array 310; 或 int array 10; 但不能写成 int array 3 ; 和 int array ;实参数组可以大于形参数组例如:实参数组定义为:int array 510; 形参数组定义为:int array 310
42、;形参数组只取实参数组的一部分,其余部分不起作用C例 写函数打印n行10列二维数组,其中n是任意整数 void print_array(int a 10, int n) int i, j; for(i=0;in; i+) for(j=0;j10;j+) printf(“%3d”, aij); printf(“n”); 例 写函数交换任意一个n*10的二维数组的i,j两行 void exchange(int a 10, int i,int j) int k, t; for(k=0;k10;k+) t=aik; aik=ajk; ajk=t; C例8.12 n行10列int型数组的每一行都有一个最
43、大值,写一函数,求这n个最大值的最小值. max_element(int a ,int m) int max, i; max= a0; for(i=1;imax) max=ai; return max; max_min( int a , int n) int i,min, max; min=max_element(a0, 10); for(i=1;imax) min=max; return min; C例 求二维数组中最大元素值1 3 5 72 4 6 815 17 34 12ijmax=11 3 5 72 4 6 815 17 34 12ijmax=31 3 5 72 4 6 815 17
44、34 12ijmax=5j1 3 5 72 4 6 815 17 34 12imax=7j1 3 5 72 4 6 815 17 34 12imax=7j1 3 5 72 4 6 815 17 34 12imax=34int max_value(int array34) int i,j,k,max; max=array00; for(i=0;i3;i+) for(j=0;jmax) max=arrayij; return(max);main() int a34=1,3,5,7, 2,4,6,8,15,17,34,12; printf(max value is %dn,max_value(a);
45、多维形参数组第一维维数可省略,第二维必须相同 int array4C例 求二维数组中各行元素之和get_sum_row(int x3, int result ,int row, int col) int i,j; for(i=0;irow;i+) resulti=0;for(j=0;jcol;j+) resulti+=xij; main() int a23=3,6,9,1,4,7; int sum_row2,row=2,col=3,i; get_sum_row(a,sum_row,row,col); for(i=0;irow;i+) printf(The sum of row%d=%dn,i+
46、1,sum_rowi);314679asum_rowxresult1812C6.8 变量的作用域与存储类别作用域生存期变量在整个程序的运行时间都存在变量只在某个函数的执行过程中才存在C6.8.1 局部变量与全局变量局部变量函数内部或复合语句内定义的变量称为局部变量例:a、v1、x的有效范围v2、x、y的有效范围m、y的有效范围C说明:、形式参数也是局部变量;、可以在复合语句中定义变量,其作用域只是本复合语句。main( ) int a, b; int c; c=a+b; c在此范围内有效a、b在此范围内有效Cvoid main( ) int i, a=0; for (i=1; i=2; i+)
47、 int a=1; a+; printf(i=%d, a=%dn, i, a); printf(i=%d, a=%dn, i, a);i=1, a=2i=2, a=2i=3, a=0全局变量定义:在函数外部定义的变量,又称为外部变量。全局变量可以为本文件中其它函数所共用其有效范围为从定义变量的位置开始到本源文件结束C例:#include int p=1, q=5;float f1(int a) int b, c; char c1, c2;char f2(int x, int y) int i, j; .main( ) int m,n; 全局变量p、q的作用域全局变量c1、c2的作用域C说明:、
48、全局变量增加了函数间的数据联系;、尽量少使用全局变量(除非在必要时);各模块间的相互联系、相互影响太多,降低了模块的独立性;会降低程序的清晰性,因为各个函数都有可能改变全局变量的值,需要时刻记住变量的当前值,编程时候容易出错。#include int k;void show( ) for (k=1; k=10; k+) putchar(*); putchar(n);C、若全局变量与局部变量同名,则在局部变量的作用范围内,全局变量不起作用;#include int a=3, b=5;int max(int a, int b) int c; c=ab ? a : b; return(c);void
49、 main( ) int a=8; printf(%d, max(a, b) );形参a、b的作用域全局变量a、b不起作用局部变量a的作用域全局变量b的作用域全局变量a不起作用讨论:如果主函数中没有int a=8,结果?C、若全局变量在文件开头定义,则在整个程序中都可以使用;若不在开头定义,其作用域只限于说明处到文件结束。如果想在定义之前的函数中引用该全局变量,则在函数中用关键字“extern”作“外部变量声明”,在函数内部,从声明之处起,可以使用它们。#include int max(int x, int y) int z; z=xy ? x : y; return(z);void main
50、( ) extern int a, b; printf(%d, max(a, b) );int a=13, b=-8;C6.8.2 变量的存储类型 结构化设计要求研究不同模块(函数、源文件)间变量的关系。变量两大属性: 数据类型 存储类别1、数据类型(复习)通过变量声明(定义)来规定其数据类型: 格式 数据类型关键字 变量名 如 char a; int b,c ; float x,y;C预留存储空间(如char型为1个字节,int型为2个字节)确定存储方式(如char型存放ASCII值,int型存放补码值)char型 01100001 (用一个字节存放该字符的ASCII值)int 型 (用两个
51、字节存放该数值的补码)float型 0110101010 011000011(四个字节)一个变量的数据类型定义后,就规定了该变量只能存储相应类型的数据 C2、存储空间的划分 程序区静态存储区动态存储区程序区:用于存放程序编译后形成的可执行代码(执行时装入)静态存储区:用于存放程序中的静态数据,如全局变量等动态存储区:用于存放程序中的动态数据,如函数形参、局部变量、函数调用时的现场保护和返回地址等静态数据说明时在静态存储区中分配存储单元并在程序执行过程中始终占用该单元,直到程序结束才释放;动态数据在函数开始执行时分配动态存储空间,函数结束时释放这些空间。C3、存储类别 规定了变量在计算机内部的存
52、放位置决定变量的“寿命”(何时“生”,何时“灭”) 一个完整的变量说明格式如下: 存储类别 数据类型 变量名 如 static int x, y;的存储类别有四种:auto、static、register和extern。 register型(寄存器型) 变量值存放在运算器的寄存器中存取速度快,一般只允许23个,且限于char型和int型,通常用于循环变量C auto型(自动变量型)变量值存放在主存储器的动态存储区(堆栈方式)优点同一内存区可被不同变量反复使用 static型(静态变量型)变量值存放在主存储器的静态存储区程序执行开始至结束,始终占用该存储空间 extern型(外部变量型)同上,其值可供其他源文件使用以上两种均属于“动态存储”性质,即调用函数时才为这些变量分配单元,函数调用结束其值自动消失。以上两种均属于“静态存储”性质,即从变量定义处开始,在整个程序执行期间其值都存在。C4、局部变量的存储方式函数中的局部变量,如不做专门的声明,都是动态分配存储空间的,存储在动态存储区中;用关键字auto作存储类型的声明。auto int b, c=3;auto float f;通常auto被省略,auto不写则隐含确定为“自动存储类别”int b, c=3;float f;局部静态变量用static声明变量为“局部静态变量”。如 static int s; static
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年版房地产买卖合同模板
- 2024年港口疏浚及堤坝修建合同3篇
- 劳动合同书电子版
- 水甲苯精馏塔课程设计
- 插班课程设计案例分析
- 管道课程设计小结
- 航空物流课程设计
- 航天研学课程设计
- 烘焙网络营销课程设计
- 机械小车课程设计
- 中药破壁饮片文稿专家讲座
- 2025年高考语文备考之名著阅读《乡土中国》重要概念解释一览表
- JG197-2006 预应力混凝土空心方桩
- 医院护理培训课件:《安全注射》
- 变、配电室门禁管理制度
- 11304+《管理案例分析》纸考2023.12
- 《浅谈跳绳体育游戏的实践研究》 论文
- 《勇敢面对挫折和困难》参考课件
- 小学体育期末检测方案
- 2023-2024学年福建省莆田市荔城区中山中学、九中联考九年级(上)期末数学试卷
- 接触网设备故障应急处理
评论
0/150
提交评论