C语言程序设计案例教程项目五-使用函数调用各功能模块课件

上传人:94****0 文档编号:241293729 上传时间:2024-06-15 格式:PPTX 页数:139 大小:11.55MB
返回 下载 相关 举报
C语言程序设计案例教程项目五-使用函数调用各功能模块课件_第1页
第1页 / 共139页
C语言程序设计案例教程项目五-使用函数调用各功能模块课件_第2页
第2页 / 共139页
C语言程序设计案例教程项目五-使用函数调用各功能模块课件_第3页
第3页 / 共139页
点击查看更多>>
资源描述
项目五使用函数调用各功能模块v教学目的:教学目的:通通过过本本章章的的学学习习,要要求求能能熟熟练练掌掌握握函函数数的的定定义义和和调调用用方方法法,掌掌握握函函数数的的嵌嵌套套调调用用和和递递归归调调用用,理理解解变变量量的的作作用用域域和和存存储储类类别别,掌掌握握内内部部函函数数和和外外部部函函数数,并并能能够够在在不不同同情情况况下下灵灵活活选选择择函函数数来来解解决决实实际际问问题题。掌掌握握编编译译预预处处理理命命令令的的使使用用方方法法。函函数数和和预预处处理理命命令令是是编编写写模模块块化化程程序序的的重重要方法,这将为编写比较复杂的程序设计的学习打下基础。要方法,这将为编写比较复杂的程序设计的学习打下基础。项目五 使用函数调用各功能模块教学目的:v教学内容教学内容 项目五使用函数调用各功能模块函数函数编译预处理编译预处理函数的定义函数的定义函数调用函数调用变量的作用域和存储类别变量的作用域和存储类别内部函数和外部函数内部函数和外部函数文件包含命令文件包含命令宏定义宏定义条件编译条件编译教学内容 项目五 使用函数调用各功能模块函数编项目五使用函数调用各功能模块重点:重点:()函数的定义和函数调用)函数的定义和函数调用(2 2)函数的参数传递)函数的参数传递难点难点 :、函数的参数传递、函数的参数传递、递归调用、递归调用、变量的作用域和存储特性、变量的作用域和存储特性v重点和难点重点和难点项目五 使用函数调用各功能模块重点:()函数任务使用函数统计课程分数信息1 1)问题情景与实现)问题情景与实现辅辅导导员员张张老老师师在在使使用用小小王王设设计计的的程程序序时时,发发现现他他分分别别要要对对每每门门课课程程学学生生成成绩绩的的总总分分及及平平均均分分进进行行计计算算,如如果果这这样样的的计计算算过过程程需需要要重重复复使使用用或或者者在在其其他他场场合合中中多多次次使使用用,使使用用以以前前的的方方法法将将使使得得程程序序代代码码重重复复书书写写,在在本本任任务务中中我我们们使使用用函函数数来来统统计计课课程程分分数数信信息息,可可以以减减少少编编程程工工作作量量,完完善善了了原原来来的的程程序序,帮帮助助张老师解决了该问题。张老师解决了该问题。任务使用函数统计课程分数信息1)问题情景与实现辅导员张任务使用函数统计课程分数信息/*功能:使用函数统计课程分数信息*/#include#defineMAX1000#defineM100floatsumM,aveM;inti,j;intcount;intcourse;floataMAXM;voidinput()printf(请输入课程的门数:);scanf(%d,&course);printf(请输入学生总人数:);scanf(%d,&count);printf(“请输入每个学生的课程成绩:”);任务使用函数统计课程分数信息/*功能:使用函数统计任务使用函数统计课程分数信息for(i=0;icount;i+)for(j=0;jcourse;j+)scanf(%f,&aij);voidsum_ave(ints,intr)for(i=0;ir;i+)sumi=0.0;for(j=0;js;j+)任务使用函数统计课程分数信息for(i=0;icount任务使用函数统计课程分数信息sumi=sumi+aji;avei=sumi/s;voidoutput()for(i=0;i0)return(1);if(x=0)return(0););if(x b)c=1;else if(a=b)c=0;else c=-1;return c;编译、连接、和运行程序。程序运行后,屏幕显示:编译、连接、和运行程序。程序运行后,屏幕显示:5.4 函数调用 5.4函数调用5.4.1函数调用的一般形式如如果果按按自自左左向向右右顺顺序序求求实实参参的的值值,则则函函数数调调用用相相当当于于compare(2,3),程程序序运运行行的的结结果果应应为为”-1”。若若按按自自右右向向左左顺顺序序求求实实参参的的值值,则则相相当当于于compare(3,3),程程序序运运行行结结果果为为”0”。如如果果不不清清楚楚自自己己所所用用的的编编译译器器对对实实参参的的求求值值顺顺序序,用用上述代码上机一试就清楚了。上述代码上机一试就清楚了。注注意意:由由于于不不同同的的编编译译器器对对实实参参的的求求值值顺顺序序不不一一样样,为为了了使使程程序序的的通通用用性性不不受受影影响响以以及及避避免免大大家家对对同同一一段段代代码码产产生生不不同同的理解,应尽量避免使用这种容易混淆的用法。的理解,应尽量避免使用这种容易混淆的用法。5.4 函数调用 5.4函数调用函函数数出出现现在在一一个个表表达达式式中中,这这种种表表达达式式称称为为函函数数表表达达式式。这时要求函数带回一个确定的值以参加表达式的运算。例如:这时要求函数带回一个确定的值以参加表达式的运算。例如:s=sum(a,b)+sum(x,y);5.4.2 5.4.2 函数调用的方式函数调用的方式1.1.函数语句函数语句按函数在程序中出现的位置来分,可以有一下三种函数按函数在程序中出现的位置来分,可以有一下三种函数调用的方式。调用的方式。把把函函数数调调用用作作为为一一个个语语句句。如如例例5.15.1中中的的printstart();printstart();这时不要求函数带返回值,只要求函数完成一些操作。这时不要求函数带返回值,只要求函数完成一些操作。2.2.函数表达式函数表达式5.4 函数调用函数出现在一个表达式中,这种表达式称为函5.4函数调用5.4.2函数调用的方式函数调用作为一个函数的参数,例如:函数调用作为一个函数的参数,例如:s=sum(a,sum(b,c);其其中中,sum(b,c)是是一一次次函函数数调调用用,它它的的值值作作为为sum另另一次调用的参数。一次调用的参数。s的值为的值为a,b,c三数的总和。三数的总和。其其实实,函函数数调调用用作作为为函函数数的的参参数数,也也是是函函数数表表达达式式调调用用的的一种形式,因为函数参数本身就是一个表达式的形式。一种形式,因为函数参数本身就是一个表达式的形式。3.3.函数参数函数参数函函 数数 sum是是 表表 达达 式式 的的 一一 部部 分分,将将 sum(a,b)的的 值值 加加 上上sum(x,y)的和赋值给的和赋值给s。5.4 函数调用 5.4函数调用如如果果一一个个函函数数要要调调用用另另外外一一个个函函数数,首首先先是是被被调调用用的的函函数数必必须须存存在在。其其次次还还应应在在主主调调函函数数中中对对所所有有被被调调函函数数加加以以说说明明,否否则则,在在连连接接时时会会出出现现找找不不到到所所调调用用函函数数的的错错误误信信息息。同同变变量量一样,函数的调用也应遵循一样,函数的调用也应遵循“先定义后使用先定义后使用”的原则。的原则。对被调函数的声明分为两种情况:对被调函数的声明分为两种情况:(1)如如果果被被调调函函数数是是C语语言言系系统统提提供供的的标标准准库库函函数数,则则在在源源程程序序文文件件的的开开头头处处,使使用用#include命命令令,将将存存放放所所调调用用库函数的有关库函数的有关“头文件头文件”包含到该程序文件中来。包含到该程序文件中来。5.4.3 5.4.3 对被调用函数的声明和函数原型对被调用函数的声明和函数原型5.4 函数调用如果一个函数要调用另外一个函数,首先是被5.4函数调用5.4.3对被调用函数的声明和函数原型#include命令的一般形式为:命令的一般形式为:#include或或#include stdio.h(2)如如果果被被调调用用函函数数为为用用户户自自己己定定义义的的函函数数,一一般般情情况况下下,应应在在主主调调函函数数中中对对被被调调用用函函数数(返返回回值值)的的类类型型进进行行说说明明。函函数数的的说说明明方方法法是是:在在主主调调函函数数的的声声明明部部分分对对被被调调函函数数进进行行声声明明。在在主主调调函函数数中中对对被被调调函函数数作作说说明明的的目目的的是是使使编编译译系系统统知知道道被被调调函函数数返返回回值值的的类类型型,以以便便在在主主调调函函数数中中按按此此种种类类型型对对返返回回值作相应的处理。值作相应的处理。5.4 函数调用 5.4.3 5.4函数调用5.4.3对被调用函数的声明和函数原型其一般形式为:其一般形式为:类型说明符类型说明符 被调函数名被调函数名(类型类型 形参,类型形参,类型 形参形参);或者:或者:类型说明符类型说明符 被调函数名被调函数名(类型,类型类型,类型);括括号号内内给给出出了了形形参参的的类类型型和和形形参参名名,或或只只给给出出形形参参类类型型。这便于编译系统进行检错,以防止可能出现的错误。这便于编译系统进行检错,以防止可能出现的错误。5.4 函数调用 5.4.3 5.4函数调用5.4.3对被调用函数的声明和函数原型例例5.1 main函数对函数对printstart()函数的说明为:函数的说明为:void printstart();例例5.2 main函数对函数对sum()函数的说明为:函数的说明为:int sum(int x,int y);也可以写成:也可以写成:int sum(int,int);5.4 函数调用 5.4.3 5.4函数调用5.4.3对被调用函数的声明和函数原型语语言言中中规规定定在在以以下下几几种种情情况况时时可可以以省省去去在在主主调调函函数数中中对对被调函数的函数说明。被调函数的函数说明。1)当当被被调调函函数数的的返返回回值值是是整整型型或或字字符符型型时时,可可以以不不对对被被调调函数作说明。这时系统会自动对被调函数返回值按整型处理。函数作说明。这时系统会自动对被调函数返回值按整型处理。例例5.3的的主主函函数数中中把把函函数数声声明明语语句句int compare(int a,int b);注释掉而直接调用就属于这种情况。注释掉而直接调用就属于这种情况。5.4 函数调用 5.4.3 5.4函数调用5.4.3对被调用函数的声明和函数原型2)2)当当被被调调函函数数的的函函数数定定义义出出现现在在主主调调函函数数之之前前时时,在在主主调调函函数数中中也也可可以以不不对对被被调调函函数数再再作作说说明明而而直直接接调调用用。例例如如例例5.15.1中中,函函数数printstart()printstart()的的定定义义放放在在 menu()menu()函函数数之之前前,因因此此可可在在 menumenu()()函函 数数 中中 省省 去去 对对 printstart()printstart()函函 数数 的的 函函 数数 说说 明明 void void printstart();printstart();3)3)如如在在所所有有函函数数定定义义之之前前,在在函函数数外外预预先先说说明明了了各各个个函函数数的的类类型型,则则在在以以后后的的各各主主调调函函数数中中,可可以以不不再再对对被被调调函函数数作作说说明。明。例如:例如:long factor(int a);long factor(int a);long sum(int b);long sum(int b);5.4 函数调用 5.4.3 5.4函数调用5.4.3对被调用函数的声明和函数原型void main()long factor(int a)long sum(int b)其其中中第第一一、二二行行对对factor函函数数和和sum函函数数预预先先作作了了说说明明。因因此此在在以以后后各各函函数数中中无无须须对对factor和和sum函函数数再再作作说说明明就就可可直接调用。直接调用。5.4 函数调用 5.4.3 5.5函数的嵌套调用和递归调用 【例例5.45.4】计算计算 =1=1!+2+2!+n+n!(n1(n1,2020的整数,从键盘输入的整数,从键盘输入)。算算法法设设计计要要点点:本本案案例例可可以以设设计计2 2个个函函数数:factor(factor()用用于于求求n n!;sum(sum()通通过过调调用用factorfactor()()来实现求来实现求。5.5.1 5.5.1 函数的嵌套调用实例函数的嵌套调用实例 /*/*源文件名:源文件名:Li5_4.c Li5_4.c 功能:求阶乘和功能:求阶乘和 */#include stdio.h#include stdio.h long factor(int n)long factor(int n)/*/*定义求阶乘函数定义求阶乘函数factor()*/factor()*/int i;int i;long f=1;long f=1;for(i=1;i=n;i+)for(i=1;i=n;i+)f=f*i;f=f*i;return f;return f;5.5 函数的嵌套调用和递归调用 【例5.4】计算=5.5函数的嵌套调用和递归调用5.5.1函数的嵌套调用实例longsum(intm)/*定义求和函数sum()*/inti;longs=0;for(i=1;i1)if(n1)f=n*factor(n-1);f=n*factor(n-1);else else f=1;f=1;return f;return f;void main()void main()int n;int n;long s;long s;printf(please input a number:);printf(please input a number:);scanf(%d,&n);scanf(%d,&n);s=factor(n);s=factor(n);/*/*调用调用factor()factor()函数函数*/printf(%d!=%ldn,n,s);printf(%d!=%ldn,n,s);5.5 函数的嵌套调用和递归调用 5.5.2 函数的嵌套调5.5函数的嵌套调用和递归调用其其中中,factorfactor函函数数在在定定义义的的过过程程中中调调用用了了本本身身,这这种种情情况况叫做函数的递归调用。叫做函数的递归调用。5.5.3 5.5.3 函数的递归调用实例函数的递归调用实例编译、连接、和运行程序。程序运行后,屏幕显示:编译、连接、和运行程序。程序运行后,屏幕显示:5.5 函数的嵌套调用和递归调用其中,factor函数在5.5函数的嵌套调用和递归调用一一个个函函数数在在它它的的函函数数体体内内调调用用它它自自身身称称为为递递归归调调用用。这这种种函函数数称称为为递递归归函函数数。语语言言允允许许函函数数的的递递归归调调用用。在在递递归归调调用用中中,主主调调函函数数又又是是被被调调函函数数。执执行行递递归归函函数数将将反反复复调调用用其其自自身身,每调用一次就进入新的一层。每调用一次就进入新的一层。下面以例下面以例5.55.5说明一下递归的执行过程。说明一下递归的执行过程。设设执执行行本本程程序序时时输输入入为为5 5,即即求求5!5!。在在主主函函数数中中的的调调用用语语句句即即为为s=factor(5);s=factor(5);,进进入入factorfactor函函数数后后,由由于于n=5,n=5,大大于于1 1,故故应应执执行行f=n*factor(n*1),f=n*factor(n*1),即即f=factor(5-1)*5f=factor(5-1)*5。该该语语句句对对factorfactor函函数作递归调用即数作递归调用即factor(4)factor(4)。5.5.4 5.5.4 函数的递归调用说明函数的递归调用说明5.5 函数的嵌套调用和递归调用一个函数在它的函数体内调进进行行四四次次递递归归调调用用后后,factorfactor函函数数形形参参取取得得的的值值变变为为1 1,故故不不再再继继续续递递归归调调用用而而开开始始逐逐层层返返回回主主调调函函数数。factor(1)factor(1)的的函函数数返返回回值值为为1 1,factor(2)factor(2)的的返返回回值值为为2*1=22*1=2,factor(3)factor(3)的的返返回回值值为为3*2=63*2=6,factor(4)factor(4)的的返返回回值值为为4*6=244*6=24,最最后后返返回回值值factor(5)factor(5)为为5*24=1205*24=120。注注意意:为为了了防防止止递递归归调调用用无无终终止止地地进进行行,必必须须在在函函数数内内有有终终止止递递归归调调用用的的手手段段。常常用用的的方方法法是是加加条条件件对对递递归归是是否否继继续续进进行行判判断断,满满足足某某种种条条件件后后就就不不再再作作递递归归调调用用,而而是是逐逐层层返返回回。如如例例5.55.5中中的的条条件件if(n1)if(n1)就就是是控控制制递递归归继继续续的的条条件件,当当n n不不小小于于1 1的时候递归就终止,开始回朔的过程。的时候递归就终止,开始回朔的过程。5.5函数的嵌套调用和递归调用5.5.4函数的递归调用说明进行四次递归调用后,factor函数形参取得的值变为1,5.6内部函数和外部函数一一个个函函数数如如果果只只能能被被本本文文件件中中其其它它函函数数所所调调用用,称称为为内内部部函函数数,内内部部函函数数又又称称静静态态函函数数。在在定定义义内内部部函函数数时时在在函函数数名名和和函数类型前面加函数类型前面加static。即:。即:static 函数类型函数类型 函数名(形参列表)函数名(形参列表)函数体函数体5.6.1 5.6.1 内部函数内部函数5.6 内部函数和外部函数一个函数如果只能被本文件中其它5.5内部函数和外部函数5.1内部函数例:例:static int fun(int a,int b)特点:只能被本文件中的函数所调用。特点:只能被本文件中的函数所调用。优优点点:不不用用担担心心与与其其它它源源文文件件中中的的函函数数同同名名,因因为为即即使使同同名也没关系。名也没关系。5.5 内部函数和外部函数 一一个个函函数数可可以以被被其其它它文文件件中中其其它它函函数数所所调调用用,就就称称为为外外部部函函数数。在在定定义义函函数数时时可可冠冠以以关关键键字字extern(省省略略也也可可),表表示此函数是外部函数。即:示此函数是外部函数。即:extern 函数类型函数类型 函数名(形参列表)函数名(形参列表)函数体函数体如:如:extern int fun(int a,int b)5.5内部函数和外部函数5.6.2 5.6.2 外部函数外部函数一个函数可以被其它文件中其它函数所调用,就称为外部函数。5.6内部函数和外部函数5.6.2外部函数特点:允许被所有源文件中的函数所调用。特点:允许被所有源文件中的函数所调用。注注意意:调调用用其其它它源源文文件件中中的的外外部部函函数数时时,需需要要对对其其进进行行说说明。明。【例例5.6】以以多多文文件件的的形形式式实实现现加加、减减、乘乘、除除和和求求余余数数运算程序运算程序说说明明:将将实实现现加加、减减、乘乘、除除和和求求余余数数运运算算的的程程序序段段分分别别作为作为1个独立的函数、存储在个独立的函数、存储在1个独立的源文件中。个独立的源文件中。5.6 内部函数和外部函数 5.6内部函数和外部函数5.6.2外部函数程序框架如下程序框架如下(完整程序详见完整程序详见【例例5.65.6】源代码源代码):分分别别创创建建addition.caddition.c源源文文件件、subtraction.csubtraction.c源源文文件件、multiplication.cmultiplication.c源源文文件件、division.cdivision.c源源文文件件、remainder.cremainder.c源源文文件件,分分别别在在各各源源文文件件中中实实现现相相应应的的加加、减减、乘乘、除除和和求求余余数函数的功能。数函数的功能。编译、连接、和运行程序。程序运行后,屏幕显示:编译、连接、和运行程序。程序运行后,屏幕显示:5.6 内部函数和外部函数 5.6内部函数和外部函数5.6.2外部函数5.6 内部函数和外部函数 5.6内部函数和外部函数在在软软件件工工程程项项目目中中,采采用用结结构构化化方方法法进进行行程程序序设设计计与与编编程程,通通常常会会产产生生多多个个源源文文件件(例例如如源源程程序序文文件件、数数据据结结构构定定义义文文件件等)。等)。那那么么,如如何何将将这这些些源源文文件件编编译译、连连接接成成一一个个统统一一的的可可执执行行文件呢?文件呢?5.6.3 5.6.3 多个源文件的编译与连接多个源文件的编译与连接5.6 内部函数和外部函数在软件工程项目中,采用结构化方5.6内部函数和外部函数5.6.3多个源文件的编译与连接一般有两种方法:一般有两种方法:1.1.分别编译、一并连接分别编译、一并连接C C编译程序是以源文件为编译单位。编译程序是以源文件为编译单位。当当一一个个程程序序中中的的函函数数和和数数据据结结构构分分放放在在多多个个源源文文件件中中时时,先先将将各各文文件件分分别别编编译译,再再通通过过linklink命命令令产产生生一一个个可可执执行行文文件件(.exe)(.exe)。2.2.集中编译、连接集中编译、连接利利用用编编译译预预处处理理命命令令#include#include,将将其其它它源源文文件件包包含含到到主主函函数数main()main()所在的源文件的开头,然后直接编译该文件即可。所在的源文件的开头,然后直接编译该文件即可。5.6 内部函数和外部函数 5.6.3 多个源文件5.6内部函数和外部函数5.6.3多个源文件的编译与连接【例例5.75.7】先先通通过过添添加加源源文文件件的的操操作作将将addition.caddition.c源源文文件件,subtraction.csubtraction.c源源文文件件,multiplication.cmultiplication.c源源文文件件,division.cdivision.c源源文文件件,remainder.cremainder.c源源文文件件添添加加到到本本工工程程(加加减减乘乘除除求求余余)来来,然后在其主函数然后在其主函数main()main()里添加如下几行:里添加如下几行:/*/*源文件名:源文件名:Li5_7.cLi5_7.c 功能:以多文件的形式实现加、减、乘、除和求余数运算功能:以多文件的形式实现加、减、乘、除和求余数运算*/*/*将其它各源文件包含进来将其它各源文件包含进来*/#include addition.c#include addition.c#include subtraction.c#include subtraction.c#include multiplication.c#include multiplication.c#include division.c#include division.c#include remainder.c#include remainder.c void main()void main()5.6 内部函数和外部函数 5.6.3 多个源文件5.7变量的作用域 局局部部变变量量也也称称为为内内部部变变量量。局局部部变变量量是是在在函函数数内内(包包括括函函数数说说明明和和函函数数体体)作作定定义义说说明明的的,其其作作用用域域仅仅限限于于函函数数内内,离开该函数后再使用这种变量是非法的。离开该函数后再使用这种变量是非法的。5.7.1 5.7.1 局部变量局部变量【例5.8】局部变量的作用域/*源文件名:Li5_8.c功能:测试局部变量的作用域*/#includestdio.hvoidtest(inta)intb=20;printf(%dn,a+b);5.7变量的作用域 局部变量也称为内部变量。局部变量是5.7变量的作用域5.7.1局部变量void main()void main()int i=2,j=3,k;int i=2,j=3,k;k=i+j;k=i+j;int k=8;int k=8;printf(%dn,k);printf(%dn,k);printf(%dn,k);printf(%dn,k);test(k);test(k);5.7变量的作用域 5.7变量的作用域5.7.1局部变量在在函函数数testtest内内定定义义了了三三个个变变量量,a a为为形形参参,b b为为一一般般变变量量。在在 testtest的的范范围围内内a a、b b有有效效,或或者者说说a a、b b变变量量的的作作用用域域限限于于testtest内。同理,内。同理,i,j,ki,j,k的作用域限于的作用域限于mainmain内。内。编译、连接、和运行程序。程序运行后,屏幕显示:编译、连接、和运行程序。程序运行后,屏幕显示:5.7变量的作用域 5.7变量的作用域5.7.1局部变量关于局部变量的作用域还要说明以下几点:关于局部变量的作用域还要说明以下几点:(1)1)主主函函数数中中定定义义的的变变量量只只能能在在主主函函数数中中使使用用,不不能能在在其其它它函函数数中中使使用用。同同时时,主主函函数数中中也也不不能能使使用用其其它它函函数数中中定定义义的的变变量量。因因为为主主函函数数也也是是一一个个函函数数,它它与与其其它它函函数数是是平平行行关关系系。这一点是与其它语言不同的,应予以注意。这一点是与其它语言不同的,应予以注意。(2)2)形形参参变变量量是是属属于于被被调调函函数数的的局局部部变变量量,实实参参变变量量是是属属于主调函数的局部变量。于主调函数的局部变量。(3)3)允允许许在在不不同同的的函函数数中中使使用用相相同同的的变变量量名名,它它们们代代表表不不同的对象,分配不同的单元,互不干扰,也不会发生混淆。同的对象,分配不同的单元,互不干扰,也不会发生混淆。(4)(4)在在复复合合语语句句中中也也可可定定义义变变量量,其其作作用用域域只只在在复复合合语语句句范围内。范围内。5.7变量的作用域 6.7变量的作用域全全局局变变量量也也称称为为外外部部变变量量,它它是是在在函函数数外外部部定定义义的的变变量量。它它不不属属于于哪哪一一个个函函数数,它它属属于于整整个个源源程程序序文文件件。其其作作用用域域是是整整个个源源程程序序。在在函函数数中中使使用用全全局局变变量量,一一般般应应作作全全局局变变量量说说明。明。只只有有在在函函数数内内经经过过说说明明的的全全局局变变量量才才能能使使用用。全全局局变变量量的的说说明明符符为为extern。但但在在一一个个函函数数之之前前定定义义的的全全局局变变量量,在该函数内使用可不再加以说明。在该函数内使用可不再加以说明。5.7.2 5.7.2 全局变量全局变量6.7变量的作用域全局变量也称为外部变量,它是在函数外5.7变量的作用域5.7.2全局变量【例例5.95.9】要要求求设设计计一一个个函函数数cuboidcuboid(double double length,length,double double width,width,double double heightheight)(3 3个个参参数数依依次次为为长长方方体体的的长长、宽宽、高高),用用于于求求长长方方体体的的体体积积及及正正、侧侧、顶顶三三个个面面的的面面积积。行数据共享。行数据共享。/*/*源文件名:源文件名:Li5_9.cLi5_9.c 功能:求长方体的体积及正、侧、顶三个面的面积功能:求长方体的体积及正、侧、顶三个面的面积 */#include stdio.h#include stdio.hdouble area1,area2,area3;/*double area1,area2,area3;/*定义定义3 3个外部变量,用于数据共享个外部变量,用于数据共享*/double cuboid(double length,double width,double height);double cuboid(double length,double width,double height);/*/*函数说明函数说明*/5.7变量的作用域 5.7变量的作用域5.7.2全局变量void main()double volume,length,width,height;printf(please input the cuboids length、width and height:);scanf(%lf%lf%lf,&length,&width,&height);volume=cuboid(length,width,height);printf(“n volume=%.2lf,area1=%.2lf,area2=%.2lf,area3=%.2lfn,volume,area1,area2,area3);double cuboid(double length,double width,double height)double volume;volume=length*width*height;/*计算体积*/area1=length*width;/*计算3个面的面积*/5.7变量的作用域 5.7变量的作用域5.7.2全局变量area2=width*height;area3=length*height;return(volume);/*返回体积值*/编译、连接、和运行程序。程序运行后,屏幕显示:编译、连接、和运行程序。程序运行后,屏幕显示:5.7变量的作用域 5.7变量的作用域5.7.2全局变量注意:注意:(1)(1)外部变量的作用域:从定义点到本文件结束。外部变量的作用域:从定义点到本文件结束。为为方方便便使使用用,建建议议将将外外部部变变量量的的定定义义放放在在文文件件开开头头,如例如例.9.9所示。所示。(2)(2)在同一源文件中,允许外部变量和内部变量同名。在同一源文件中,允许外部变量和内部变量同名。在内部变量的作用域内,外部变量不起作用。在内部变量的作用域内,外部变量不起作用。(3)(3)外外部部变变量量可可实实现现函函数数之之间间的的数数据据共共享享,但但又又使使这这些些函函数依赖这些外部变量,因而使得这些函数的独立性降低。数依赖这些外部变量,因而使得这些函数的独立性降低。从从模模块块化化程程序序设设计计观观点点来来看看,这这是是不不利利的的。因因此此不不是是非非用用不不可可时,不要使用外部变量。时,不要使用外部变量。5.7变量的作用域 5.8变量的存储类别 语语言言中中的的变变量量,不不仅仅有有类类型型特特性性,还还有有存存储储特特性性,从从变变量量值值存存在在的的时时间间(即即生生存存期期)角角度度来来分分,可可以以分分为为静静态态存存储方式和动态存储方式。储方式和动态存储方式。1动动态态存存储储方方式式:是是在在程程序序运运行行期期间间根根据据需需要要进进行行动动态的分配存储空间的方式。态的分配存储空间的方式。自动内部变量自动内部变量(auto)、寄存器变量、寄存器变量(register)5.8.1 5.8.1 动态存储和静态存储动态存储和静态存储5.8 变量的存储类别 语言中的变量,不仅有类型特性5.8变量的存储类别5.8.1动态存储和静态存储2 2静静态态存存储储方方式式:是是指指在在程程序序运运行行期期间间分分配配固固定定的的存存储储空间的方式。静态内部变量空间的方式。静态内部变量(static)(static)、外部变量、外部变量(extern)(extern)。用户存储空间可以分为三个部分:用户存储空间可以分为三个部分:(1)(1)程序区;程序区;(2)(2)静态存储区;静态存储区;(3)(3)动态存储区;动态存储区;5.8 变量的存储类别 5.5.8变量的存储类别5.8.1动态存储和静态存储全全局局变变量量全全部部存存放放在在静静态态存存储储区区,在在程程序序开开始始执执行行时时给给全全局局变变量量分分配配存存储储区区,程程序序运运行行结结束束就就释释放放。在在程程序序执执行行过过程程中中它们占据固定的存储单元,而不动态地进行分配和释放;它们占据固定的存储单元,而不动态地进行分配和释放;动态存储区存放以下数据:动态存储区存放以下数据:1)1)函数形式参数;函数形式参数;2)2)自动变量(未加自动变量(未加staticstatic声明的局部变量);声明的局部变量);3)3)函数调用时的现场保护和返回地址;函数调用时的现场保护和返回地址;对对以以上上这这些些数数据据,在在函函数数开开始始调调用用时时分分配配动动态态存存储储空空间间,函函数数结束时释放这些空间。结束时释放这些空间。5.8 变量的存储类别 5.5.8变量的存储类别5.8.2 5.8.2 动态存储动态存储【例5.10】动态存储举例/*源文件名:Li5_10.c功能:测试动态存储变量的空间分配情况*/#includestdio.hvoidtest()intm=10;m+;printf(m=%dn,m);5.8 变量的存储类别5.8.2 动态存储 【例55.8变量的存储类别5.8.2动态存储void main()void main()printf(the first time:);printf(the first time:);test();test();printf(the second time:);printf(the second time:);test();test();printf(the third time:);printf(the third time:);test();test();5.8 变量的存储类别 5.8变量的存储类别5.8.2动态存储编译、连接、和运行程序。程序运行后,屏幕显示:编译、连接、和运行程序。程序运行后,屏幕显示:5.8 变量的存储类别 5.8变量的存储类别5.8.2动态存储函函数数中中的的局局部部变变量量,如如不不特特别别声声明明为为staticstatic存存储储类类别别,都都是是动动态态地地分分配配存存储储空空间间的的,数数据据存存储储在在动动态态存存储储区区中中。函函数数中中的的形形参参和和在在函函数数中中定定义义的的变变量量(包包括括在在复复合合语语句句中中定定义义的的变变量量)都都属属此此类类,在在调调用用该该函函数数时时系系统统会会给给它它们们分分配配存存储储空空间间,在在函函数数调调用用结结束束时时就就自自动动释释放放这这些些存存储储空空间间。这这类类局局部部变变量量称称为为自自动动变变量量。自自动动变变量量用用关关键键字字autoauto(autoauto可可以以省省略)作存储类别的声明。略)作存储类别的声明。5.8 变量的存储类别 5.8变量的存储类别5.8.2动态存储如例如例5.105.10中,中,testtest函数中的函数中的m m没有用没有用staticstatic声明,说声明,说明它就是一个自动变量,所以,在主函数中调用了三次的明它就是一个自动变量,所以,在主函数中调用了三次的testtest函数,每次得到的函数,每次得到的m m的输出值都是一样的,这是因为的输出值都是一样的,这是因为自动变量只有在函数被调用的时候分配空间,当函数调用自动变量只有在函数被调用的时候分配空间,当函数调用结束,空间也就自动释放了,所以每次调用结束,空间也就自动释放了,所以每次调用m m都是被重新都是被重新赋初始值赋初始值1010。5.8 变量的存储类别 5.8变量的存储类别5.8.3 5.8.3 用用staticstatic声明的局部变量声明的局部变量【例5.11】静态局部变量例题/*源文件名:Li5_11.c功能:测试静态局部变量的空间分配情况*/#includestdio.hvoidtest()staticintm=10;/定义m为静态局部变量m+;printf(m=%dn,m);5.8 变量的存储类别5.8.3 用static声明的局部5.8变量的存储类别5.8.3用static声明的局部变量void main()printf(the first time:);test();printf(the second time:);test();printf(the third time:);test();5.8 变量的存储类别 5.8.3 5.8变量的存储类别5.8.3用static声明的局部变量有有时时希希望望函函数数中中的的局局部部变变量量的的值值在在函函数数调调用用结结束束后后不不消消失失而而保保留留原原值值,这这时时就就应应该该指指定定局局部部变变量量为为“静静态态局局部部变变量量”,用用关关键键字字staticstatic进进行行声声明明。如如例例6.116.11中中testtest函函数数中中的的m m变变量量被被用用staticstatic声声明明位位静静态态局局部部变变量量。由由于于静静态态变变量量在在程程序序运运行行期期间间的的被被分分配配的的存存储储空空间间是是固固定定的的。所所以以第第一一次次调调用用testtest函函数数的的时时候候,m m变变量量空空间间被被分分配配,并并且且赋赋予予初初值值1010,然然后后执执行行m+m+操操作作,所所以以m m的的值值就就为为11.11.但但调调用用结结束束的的时时候候m m的的空空间间仍仍然然存存在在,没没有有因因函函数数调调用用结结束束而而被被释释放放。所所以以在在testtest函函数数第第二二次次被被调调用用的的时时候候,m m不不再再重重新新分分配配空空间间和和初初始始化化为为1010,而而是是使使用用原原来来的的空空间间,沿沿用用上上一一次次的的值值1111,故第二次调用的时候输出的,故第二次调用的时候输出的m m值为值为1212,第三次为,第三次为1313。5.8 变量的存储类别 5.8.3 5.8变量的存储类别5.8.3用static声明的局部变量对静态局部变量的说明:对静态局部变量的说明:(1)1)静静态态局局部部变变量量属属于于静静态态存存储储类类别别,在在静静态态存存储储区区内内分分配配存存储储单单元元。在在程程序序整整个个运运行行期期间间都都不不释释放放。而而自自动动变变量量(即即动动态态局局部部变变量量)属属于动态存储类别,占动态存储空间,函数调用结束后即释放。于动态存储类别,占动态存储空间,函数调用结束后即释放。(2)2)静静态态局局部部变变量量在在编编译译时时赋赋初初值值,即即只只赋赋初初值值一一次次;而而对对自自动动变变量量赋赋初初值值是是在在函函数数调调用用时时进进行行,每每调调用用一一次次函函数数重重新新给给一一次次初初值值,相相当当于执行一次赋值语句。于执行一次赋值语句。(3)3)如如果果在在定定义义局局部部变变量量时时不不赋赋初初值值的的话话,则则对对静静态态局局部部变变量量来来说说,编编译译时时自自动动赋赋初初值值0 0(对对数数值值型型变变量量)或或空空字字符符(对对字字符符变变量量)。而而对对自动变量来说,如果不赋初值则它的值是一个不确定的值。自动变量来说,如果不赋初值则它的值是一个不确定的值。5.8 变量的存储类别 5.8.3 5.8变量的存储类别为为了了提提高高效效率率,C语语言言允允许许将将局局部部变变量量的的值值放放在在CPU的的寄寄存存器器中中,这这种种变变量量叫叫“寄寄存存器器变变量量”,用用关关键键字字register作声明。作声明。5.8.4 register5.8.4 register变量变量/*源文件名:Li5_12.c功能:测试寄存器存储变量的空间分配情况*/#includestdio.hintfactor(intn)registerinti,f=1;for(i=1;i=n;i+)f=f*i;returnf;5.8 变量的存储类别为了提高效率,C语言允许将局部变5.8变量的存储类别5.8.4register变量void main()void main()int i;int i;for(i=0;i=5;i+)for(i=0;i=5;i+)printf(%d!=%dn,i,factor(i);printf(%d!=%dn,i,factor(i);5.8 变量的存储类别 5.8变量的存储类别5.8.4register变量编译、连接、和运行程序。程序运行后,屏幕显示:编译、连接、和运行程序。程序运行后,屏幕显示:5.8 变量的存储类别 5.8变量的存储类别5.8.4register变量注意:注意:(1)(1)只有局部动态变量和形式参数可以作为寄存器变量;只有局部动态变量和形式参数可以作为寄存器变量;(2)(2)一一个个计计算算机机系系统统中中的的寄寄存存器器数数目目有有限限,不不能能定定义义任任意意多个寄存器变量;多个寄存器变量;(3)(3)局部静态变量不能定义为寄存器变量;局部静态变量不能定义为寄存器变量;(4)register(4)register型变量不能为型变量不能为long,double,floatlong,double,float型。型。5.8 变量的存储类别 5.8变量的存储类别前前面面介介绍绍过过,在在函函数数外外部部定定义义的的变变量量称称为为外外部部变变量量。如如果果一一个个程程序序由由多多个个源源文文件件构构成成,根根据据某某个个源源文文件件中中定定义义的的外外部部变变量量能能否否被被其其它它源源文文件件中中的的函函数数所所引引用用,将将外外部部变变量量分分为为两个作用域级别:两个作用域级别:(1)文文件件级级外外部部变变量量只只允允许许被被本本源源文文件件中中的的函函数数引引用,其定义方式如下:用,其定义方式如下:static 数据类型数据类型 外部变量表;外部变量表;(2)程程序序级级外外部部变变量量允允许许被被程程序序中中各各源源文文件件内内的的函函数引用,其定义方式如下:数引用,其定义方式如下:extern 数据类型数据类型 外部变量表;外部变量表;5.8.5 5.8.5 文件级外部变量和程序级外部变量文件级外部变量和程序级外部变量5.8 变量的存储类别前面介绍过,在函数外部定义的变量5.8变量的存储类别5.8.5文件级外部变量和程序级外部变同同一一程程序序中中的的其其它它源源文文件件内内的的函函数数如如果果想想引引用用程程序序级级外外部部变量时,需要对其进行说明。变量时,需要对其进行说明。有有效效范范围围:从从定定义义变变量量的的位位置置开开始始到到本本源源文文件件结结束束,及及有有externextern说明的其它源文件。说明的其它源文件。注意:注意:(1 1)externextern不是变量定义不是变量定义,但可扩展外部变量作用域。但可扩展外部变量作用域。(2 2)若外部变量与局部变量同名,则外部变量被屏蔽。)若外部变量与局部变量同名,则外部变量被屏蔽。5.8 变量的存储类别 5.8.5 文件级外部变量5.8变量的存储类别5.8.5文件级外部变量和程序级外部变下面用图表对变量的存储类型进行一个系统的归纳下面用图表对变量的存储类型进行一个系统的归纳:5.8 变量的存储类别 5.8.5 文件级外部变量5.9编译预处理在在前前面面各各章章中中,已已多多次次使使用用过过以以“#”开开头头的的预预处处理理命命令令。如如包包含含命命令令#include,宏宏定定义义命命令令#define等等。在在源源程程序序中中这这些些命命令令都都放放在在函函数之外,而且一般都放在源文件的前面,它们称为编译预处理部分。数之外,而且一般都放在源文件的前面,它们称为编译预处理部分。所所谓谓编编译译预预处处理理是是指指在在进进行行编编译译的的第第一一遍遍扫扫描描(词词法法扫扫描描和和语语法法分分析析)之之前前所所作作的的工工作作。预预处处理理是是语语言言的的一一个个重重要要功功能能,它它由由预预处处理理程程序序负负责责完完成成。当当对对一一个个源源文文件件进进行行编编译译时时,系系统统将将自自动动引引用用预预处处理理程程序序对对源源程程序中的预处理部分作处理,处理完毕自动进入对源程序的编译。序中的预处理部分作处理,处理完毕自动进入对源程序的编译。语语言言提提供供了了多多种种预预处处理理功功能能,如如宏宏定定义义、文文件件包包含含、条条件件编编译译等等。合合理理地地使使用用预预处处理理功功能能编编写写的的程程序序便便于于阅阅读读、修修改改、移移植植和和调调试试,也也有有利于模块化程序设计。本节主要介绍常用的几种预处理功能。利于模块化程序设计。本节主要介绍常用的几种预处理功能。5.9 编译预处理在前面各章中,已多次使用过以“#”开.8变量的存储类别文文件件包包含含由由#include 命命令令来来说说明明,编编译译预预处处理理时时,系系统统将将包包含含文文件件的的内内容容插插入入到到程程序序中中引引用用它它的的地地方方,即即程程序序中中相相应应的的#include命命令令所所在在处处.文文件件包包含含是是指指一一个个源源文文件件可可以以将将另另一一个个源源文文件件的的全全部部内内容容包包含含进进来来.有有两两种种形形式式:#include 和和#include”文件名文件名”。1)每每行行写写一一句句,只只能能写写一一个个文文件件名名,结结尾尾不不加加分分号号;。被包含的文件必须是源文件而不能是目标文件。被包含的文件必须是源文件而不能是目标文件。2)一一个个include命命令令只只能能指指定定一一个个被被包包含含文文件件,若若有有多个文件要包含,则需用多个多个文件要包含,则需用多个include命令。命令。5.9.1#include5.9.1#include命令命令.8 变量的存储类别文件包含由#include 命令5.9编译预处理5.9.1#include命令3)3)文文件件包包含含可可以以嵌嵌套套。即即一一个个被被包包含含文文件件中中,可可以以包包含含另另一一个被包含文件。个被包含文件。4)4)在在#include#include命命令令中中,文文件件名名可可以以用用尖尖括括号号或或双双引引号号括括起起来来,二二者者都都是是合合法法的的。其其区区别别是是用用尖尖括括号号时时,系系统统到到存存放放C C库库函函数数头头文文件件所所在在的的目目录录中中去去寻寻找找要要包包含含的的文文件件。用用双双引引号号时时,系系统统先先在在用用户户当当前前目目录中寻找要包含的文件录中寻找要包含的文件,若找不到若找不到,再按标准方式查找。再按标准方式查找。在在程程序序设设计计中中,文文件件包包含含是是很很有有用用的的。一一个个大大的的程程序序可可以以分分为为多多个个模模块块,由由多多个个程程序序员员分分别别编编程程。有有些些公公用用的的符符号号常常量量或或宏宏定定义义等等可可单单独独组组成成一一个个文文件件,在在其其它它文文件件的的开开头头用用包包含含命命令令包包含含该该文文件件即即可可使使用用。这这样样可可避避免免在在每每个个文文件件开开头头都都去去书书写写那那些些公公用用量量,从从而而节省时间,并减少出错。节省时间,并减少出错。5.9 编译预处理 在在语语言言源源程程序序中中允允许许用用一一个个标标识识符符来来表表示示一一个个字字符符串串,称称为为”宏宏”。被被定定义义为为“宏宏”的的标标识识符符称称为为”宏宏名名”。在在编编译译预预处处理理时时,对对程程序序中中所所有有出出现现的的”宏宏名名”,都都用用宏宏定定义义中中的字符串去代换,这称为的字符串去代换,这称为”宏代换宏代换”或或”宏展开宏展开”。宏宏定定义义是是由由源源程程序序中中的的宏宏定定义义命命令令完完成成的的,宏宏代代换换是是由由预处理程序自动完成的。预处理程序自动完成的。在在语语言言中中,”宏宏”分分为为有有参参数数和和无无参参数数的的两两种种。下下面面分别讨论这两种分别讨论这两种“宏宏”的定义和调用。的定义和调用。5.9.2 5.9.2 宏定义宏定义5.9编译预处理在语言源程序中允许用一个标识符来表示一个字符串,称为”5.9编译预处理5.9.2
展开阅读全文
相关资源
相关搜索

最新文档


当前位置:首页 > 办公文档 > 教学培训


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!