版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第10章函数写一篇文章,如果只有几百字,只需简单地分段,就可以得到比较清晰的文章结构;但是如果是几十页或几百页的长篇论文,那么就必须把内容按照一定的次序分成多个章节来论述。写程序也是一个道理:只是几十行的话,可以简单地放在main函数中,通过空行和注释等手段来说明程序的段落;当程序有几百、几千甚至几万行时,就需要对程序分节、分章甚至分篇。C语言提供了函数来帮助程序员对程序实现分节、分章或分篇的工作。本章将学习函数在C语言中的作用和使用函数时需要注意的一些问题。第10章函数在本章的学习中,要重点掌握以下内容:模块化编程思想;函数的作用;函数的声明;函数的形参列表;使用const形参;main函数的标准形式;如何向main函数传值以及如何取得main函数的值。10.1什么是函数函数是程序实现模块化编程的基本单元,一般是完成某一特定功能的语句的集合;它可以提高程序的可读性和可维护性,并可以提高代码重用率。本节先介绍模块化编程的思想,再介绍函数的定义和调用,并通过一个简单范例来演示函数的使用。10.1.1模块化编程所谓模块化编程是指将程序划分为一系列功能相互独立的模块,再以模块为单元进行开发,最后合并到主程序的编程方法。在C语言中,会把功能独立且完整的模块封装在函数中,由函数提供对外的接口,再在外部函数调用。这种模块化编程是C语言面向过程编程的基本方法。10.1.2定义函数函数的定义由函数声明和函数体两部分组成。函数声明又可以分为由函数返回值类型、函数名、参数列表、函数体以及函数操作符5个部分组成。标准形式如下:函数返回值类型函数名(参数类型1参数名1,参数类型1参数名2,…){/*函数体*/变量定义;函数操作;return语句;}10.1.2定义函数函数声明也可以称为函数原型,定义了函数作为模块化编程的基本单元的接口:函数值类型对应模块出口,函数名对应模块名,参数列表对应了模块入口。函数返回值类型也称为函数值类型,是由函数带回的值的类型。函数名是函数的标志符,其命名规范与其余变量名一致;但是函数名应该能很清晰地反应函数操作的内容。参数列表是函数的传入参数列表,依次将放在函数操作符,即小括号中。函数体,也被称为函数块,是一个放在花括号内的复合语句。它包括三个部分:变量定义部分,函数操作部分,return语句。10.1.3调用函数函数调用表达式由函数名、函数操作符和逗号表达式三部分组成。逗号表达式一般为由逗号隔开的若干个子表达式的集合。如下所示:函数名(参数表达式1,参数表达式2,…)函数名指明被调用的函数的名称。逗号表达式一般为由逗号隔开的若干个子表达式的集合,子表达式的个数必须与被调用的函数声明的参数个数相同;如果函数声明中的参数列表为空,逗号表达式也必须为空。10.1.3调用函数参数表达式与函数申明中的参数按从左到右的顺序一一对应,每个表达式的值类型必须与函数声明中的相应参数类型一致;否则调用函数时,编译器会自动进行类型转换。如果转换失败,那么这个函数调用就是错误的。函数调用表达式的值由函数定义中的return语句的表达式值决定,类型为函数声明中的函数值类型。10.1.3调用函数函数调用以及函数代码的执行过程如下:(1)运行到函数调用表达式,先寻找具有该函数名的函数定义,再将函数声明与函数定义的第一行进行比较,函数返回值必须一致,形参个数必须与函数调用语句中的实参个数相同,同时实参类型必须能自动转换为形参类型。(2)得到函数声明后,准备执行函数代码。编译器保存主调函数的执行状态,以便于函数执行完毕后继续执行主调函数代码。10.1.3调用函数(3)开始执行函数,将函数调用表达式中的各个实参值传递给函数定义中相应的各个形参,必要的情况下会自动执行类型转换。这个过程叫“参数传递”。这时,形参才分配到内存空间。(4)执行函数体代码。如果有return语句,执行到return语句后,函数结束;如果函数中没有return语句,会依次执行完函数体所有代码。(5)函数结束后,编译器恢复在执行函数代码前保存的主调函数的执行状态,将函数返回值带入到函数调用表达式所在语句,继续代码。10.1.3调用函数按照函数调用表达式出现的位置,函数调用方式可分为以下三种形式:1.单独语句函数调用表达式可以单独作为语句使用。例如范例10-1中调用void型函数print_array和void型函数transpose_array的语句,如下所示:print_array(array);transpose_array(array,transpose);10.1.3调用函数2.子表达式函数调用表达式还可以作为语句的一个子表达式使用,如下所示:b=square(5); /*要求函数值类型不为void型*/print_array(array),transpose_array(array,transpose); /*函数值类型可以为void型*/3.函数实参函数调用表达式还可以作为函数参数,这实际上是第二种情况的特殊方式。实例如下:c=max(a,min(a,b));/*要求min函数返回类型不为void型*/d=min(a,min(a,b));/*要求min函数返回类型不为void型*/10.1.4函数使用举例下面围绕一个范例来讨论函数的使用。该范例将加法、减法和乘法运算封装在函数中,通过函数调用来实现两个数的加法、减法和乘法运算。10.1.5范例的改进对于范例10-2中的函数体代码和函数调用代码还可以进行适当改进。其中,sum函数、dif函数和pro函数中定义的变量tmp都是临时变量,可以省略。例如,函数sum的实现与下面这段相对简单的代码功能完全一样,代码如下:intsum(constinta,constintb){returna+b;}10.2函数声明如前文所述,一个完整的函数声明包括函数值类型、函数名和参数列表三个部分组成。完整的函数声明定义了一个功能模块的接口。本小节将介绍函数声明的标准形式,将声明与定义进行比较,让读者更清楚两者的关系;然后将依次讨论函数声明中的函数值和参数列表,最后还讨论了函数怠const形参等问题。10.2.1声明的形式函数声明可以作为单独语句使用,形式如下:函数值类型函数名(参数类型1形参1,参数类型2形参2,…)例如,范例10-3中的四个函数声明分别如下:voidprint_data(constinta,constintb)intsum(constinta,constintb)intdif(constinta,constintb)intpro(constinta,constintb)10.2.1声明的形式函数也可以视为一个变量,函数声明即变量声明,函数名即变量名。该函数变量的类型可以称为函数类型,其形式一般为函数声明中去掉函数名的剩余部分,即:函数值类型(参数类型1形参1,参数类型2形参2,…);由于函数操作符为后置操作符,必须放在变量名后面,所以声明函数型变量时,变量名得放在函数操作符前(与数组类型相似)。所以上面的4个函数类型名分别如下:print_data的类型为:void(constinta,constintb)sum的类型为:int(constinta,constintb)dif的类型为:int(constinta,constintb)pro的类型为:int(constinta,constintb)10.2.1声明的形式又例如,范例10-1中的两个函数声明如下:voidprint_array(intarray[SIZE][SIZE])voidtranspose_array(intarray[SIZE][SIZE],inttranspose[SIZE][SIZE])这两行语句可以视为声明了两个函数变量,其中变量print_array的类型被声明为:void(intarray[SIZE][SIZE])而变量transpose_array的类型被声明为:void(intarray[SIZE][SIZE],inttranspose[SIZE][SIZE])10.2.2声明与定义与变量一样,函数的声明和定义也是有严格区别的。函数声明确定了一个函数的接口,告诉编译器该函数的函数名、函数值类型以及形参列表中形参的个数和顺序;而函数定义则确立了一个函数的功能,不仅仅包含了函数声明所有的信息,还包含了形参的名字和函数体。在C程序中,一个函数变量可以被多次声明(当然,所有声明不能冲突),但是函数定义只能有一个。函数定义不能放在其他函数内,而函数声明则可以。提示:函数定义之外的声明中的形参列表的所有参数类型名必须与函数定义中的参数类型一致,但是声明的参数名可以不一样。实际上,函数定义外的函数声明中的参数名是没有用处的。10.3.1函数值类型函数值类型可以是整型、浮点型、字符型,也可以是自定义类型(typedef的结果)。下面是几个函数声明的实例:01 intget_value(void);02 doublemax(doublenum1,doublenum2);03 charupletter(charc);10.3.1函数值类型例如,需要返回一个char型数组的函数,其声明形式如下:char*function(形参列表);其中,char*是一个char型指针类型。10.3.2形参列表1.形参列表的两种形式作为函数定义一部分的函数声明中,形参列表必须为每个参数的声明类型和参数名,例如:函数值类型函数名(参数类型1形参名1,参数类型2形参名2,…);而在函数定义外的函数声明中,参数列表中可以只列出参数类型,如下所示:函数值类型函数名(参数类型1,参数类型2,…);10.3.2形参列表2.使用空列表参数列表也可以是空的,表示没有参数。例如,范例10-5中第11行的就声明了一个参数列表为空的函数,如下所示:inthello_mark(void)也可以写为:inthello_mark()要声明一个无形参的函数时,建议使用void型作为函数列表内容,以显式地说明不需要参数。10.3.2形参列表3.实参到形参的值传递调用函数时,只能把实参的值传递给形参,而形参不能改变实参的值。二者之间的值传递过程可以简单地理解为:调用函数后,每个形参都初始化为相对应的实参,如下所示:参数类型1形参1=实参1;参数类型2形参2=实参2;……10.3.3函数值当函数值类型不为void型时,函数返回值就可以作为函数调用表达式中的一个操作数来使用。一个函数的函数值一般有两种用途:1.信息载体函数可以使用return语句将函数内的某个值带到函数外,如果需要返回的信息只需要一个数值来传递,那么可以选择将这个信息作为返回值带到函数外。下面是两个把返回值作为信息载体的例子。10.3.3函数值2.指示执行状态当函数的执行有多个分支,而函数外部又需要知道函数内部执行的是哪一个分支时,可以在函数内部使用一个标志变量来记录执行的分支,最后使用return语句将该值返回。在函数外部,通过检查该标志的值,就可以判断函数执行了那一个分支。10.3.4使用const形参在第4.5节中已经讨论了关于const限定词的功能和使用方法。在本章之前的程序代码中,很多形参在声明中也使用了const限定词,其作用是为了避免只读变量被修改,即声明为const变量的形参在函数中不能被修改,这样做还可以最大限度地利用编译器的优化功能。10.3.4使用const形参下列是前面的程序中的使用了const限定词的部分函数声明:intsum(constinta,constintb) /*范例10-3第4行*/intdif(constinta,constintb) /*范例10-3第12行*/intpro(constinta,constintb) /*范例10-3第16行*/intcube(constintx) /*范例10-7第4行*/intsearch_data(constintarray[],constintsize,constinttarget) /*范例10-8第7行*/10.4函数体函数体是函数的具体功能操作的代码实现,是C函数的主体。在前面已经简要地介绍过函数体一般由变量定义、函数操作和return语句三部分组成。本节将讨论函数体的一些特性以及编写函数体需要注意的问题。注意:函数体可以为空。函数体为空的函数的什么都不做,不会执行任何操作。例如:voidcreateButton(constintname,intflag){}10.4.1定义变量变量定义就是定义函数中需要用到的变量。C函数中的变量定义必须都放在函数体的最前面,允许变量定义之间有空行,但不能包括函数操作。10.4.2检查形参由于形参值从实参而来,如果调用时使用了异常的实参值,就有可能导致函数执行时发生一些异常错误。因此,在函数体中对形参进行操作前,有必要先检查形参值的合法性。10.4.3return语句C函数中的return语句的功能是计算返回值,并结束函数。return语句一般由关键字return和表达式两部分组成,如下:return表达式;执行该语句时,先计算表达式的值,该值为函数返回值,再结束函数。10.5main函数main函数是C语言中的最特殊的函数。它是C程序的入口,每一个C程序都必须包含main函数。但是由于一些历史的原因,导致main函数的声明和使用有些混乱。本节将按照C99标准来介绍main函数的标准声明形式和函数值类型,以及如何向main函数传递参数,最后还讨论了main函数的函数值。10.5.1main函数的声明main函数也是函数,它的标准声明也含有函数值类型和形参列表。C99标准规定,main的返回值类型必须为int,而形参列表可以为空,也可以带两个两个形参。其标准声明形式如下:intmain(void)intmain(intargc,char*argv[])其中,第二种声明方式可以从外面程序接收参数。变量argc为int型,保存参数个数;变量argv为字符串数组型,以字符串数组形式保存传入参数的内容。警告:除上述两种声明方法之外的其余所有声明方法都是不建议使用或是错误的。10.5.2函数值类型C99标准中,只接受返回值类型为int型的main函数。但是,在使用main函数时,有的程序员甚至介绍C语言的书常常会将函数值类型省略或者声明为void型。省略函数值类型时不推荐的,而声明为void型则是错误的。10.5.2函数值类型1.不能省略函数值类型由于C语言一开始只有int型一种数据类型,所以开始的main函数返回类型都是int型。既然只可能是一种类型,因此实现时便允许省略返回类型,可以写为:main()或main(intargc,char*argv[])这种写法在C89标准中是可以接受的,大部分C编译器为了兼容之前的版本也允许这种声明方法。但这是不建议的声明方法,在C99标准中要求编译器要对这种用法给以警告。10.5.2函数值类型2.不能使用void型作为函数值类型在C语言中,当一个函数function无需返回值时,可以将其声明为void型,例如:voidfunction(void);因此,有的程序员就以为如果main函数不需要返回值时,也可以声明为void型,如下所示:voidmain(void)或voidmain(intargc,char*argv[])有些编译器(例如VisualC++6.0)也接受这种声明方法,C标准中明确规定main函数的返回值类型为int型,因此这种声明方法是错误的。10.5.2函数值类型3.可以使用自定义类型作为函数值类型返回值类型也可以使用typedef自定义的数据类型名来代替,例如:#defineintBIT32BIT32main(void);或#defineintBIT32BIT32main(intargc,char*argv[])10.5.3向main函数传递参数main函数的形参列表可以为void型,此时main函数不接受任何传入参数;也可以带两个形参,int型变量和字符串数数组型变量,变量名建议为argc和argv。声明如下:intmain(intargc,char*argv[])其中,argc的类型名int型也可以使用typedef自定义的数据类型名来代替,例如:#defineintBIT32intmain(BIT32argc,char*argv[])10.5.3向main函数传递参数char
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 旅游行业人力资源开发与培训汇报
- 供应链风险管理与控制
- 戏曲花旦化妆课程设计
- 青岛工程职业学院《高频电子技术》2023-2024学年第一学期期末试卷
- 数字王用表课程设计
- 中国电影产业发展现状及未来趋势预测
- 智能制造成功案例分享汇报
- 商业演讲中的技巧
- 招投标合同管理课程设计
- 个人能力提升与职业发展策略
- 期末 (试题) -2024-2025学年人教PEP版英语五年级上册
- 乡村少年宫英语组活动记录
- 关键工序验收一般要求详解
- GB 37489.3-2019 公共场所设计卫生规范 第3部分:人工游泳场所(高清版)
- 科学研究基金项目延期申请书
- 《故都的秋》(郁达夫)第一课时教学设计
- JGJ_T139-2020玻璃幕墙工程质量检验标准(高清-最新版)
- 2022高端新款个人简历模板(可编辑)2 (9)
- 运动特质自信量表
- 肺结核CT征象分析PPT课件
- (精选)工程项目成本责任制管理办法(试行)
评论
0/150
提交评论