第3章-函数和编译预处理

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

第3章函数和编译预处理3.1函数概述3.2函数的定义和调用3.3函数的参数传递3.4函数的嵌套调用和递归调用3.5内置函数3.6变量和函数的属性3.7编译预处理3.1概述一个较大的程序不可能完全由一个人从头至尾地完成,更不可能把所有的内容都放在一个主函数中。为了便于规划、组织、编程和调试,一般的做法是把一个大的程序划分为若干个程序模块(即程序文件),每一个模块实现一部分功能。不同的程序模块可以由不同的人来完成。在程序进行编译时,以程序模块为编译单位,即分别对每一个编译单位进行编译。如果发现错误,可以在本程序模块范围内查错并改正。在分别通过编译后,才进行连接,把各模块的目标文件以及系统文件连接在一起形成可执行文件。在一个程序文件中可以包含若干个函数。无论把一个程序划分为多少个程序模块,只能有一个main函数。程序总是从main函数开始执行的。在程序运行过程中,由主函数调用其他函数,其他函数也可以互相调用。在C语言中没有类和对象,在程序模块中直接定义函数。可以认为,一个C程序是由若干个函数组成的,C语言被认为是面向函数的语言。C++面向过程的程序设计沿用了C语言使用函数的方法。在C++面向对象的程序设计中,主函数以外的函数大多是被封装在类中的。主函数或其他函数可以通过类对象调用类中的函数。无论是C还是C++,程序中的各项操作基本上都是由函数来实现的,程序编写者要根据需要编写一个个函数,每个函数用来实现某一功能。因此,读者必须掌握函数的概念以及学会设计和使用函数。“函数”这个名词是从英文function翻译过来的,其实function的原意是“功能”。顾名思义,一个函数就是一个功能。在实际应用的程序中,主函数写得很简单,它的作用就是调用各个函数,程序各部分的功能全部都是由各函数实现的。主函数相当于总调度,调动各函数依次实现各项功能。开发商和软件开发人员将一些常用的功能模块编写成函数,放在函数库中供公共选用。程序开发人员要善于利用库函数,以减少重复编写程序段的工作量。图3.1是一个程序中函数调用的示意图。图3.1main()func1()func2()func3()func5()func4()例3.1在主函数中调用其他函数。#includeiostream.h//*****ex3_1.cpp*****intcalc_sum(intn)//定义calc_sum()函数{intk,s;s=0;for(k=1;k=n;k++)s=s+k;returns;}voidprint_word(void)//定义print_word()函数{coutHello,C++!endl;//输出一行文字}voidmain(void){intn;cinn;if(n1)coutthesumis:calc_sum(n)endl;//调用calc_sum()函数print_word();//调用rint_word()函数}若用户从键盘输入的数是4,运行情况如下:thesumis:10Hello,C++!从用户使用的角度看,函数有两种:(1)系统函数,即库函数。这是由编译系统提供的,用户不必自己定义这些函数,可以直接使用它们。(2)用户自己定义的函数。用以解决用户的专门需要。从函数的形式看,函数分两类:(1)无参函数。调用函数时不必给出参数。(2)有参函数。在调用函数时,要给出参数。在主调函数和被调用函数之间有数据传递。3.2函数的定义和调用3.2.1定义无参函数的一般形式定义函数的一般形式如下:类型标识符函数名([形式参数列表]){声明语句执行语句}【例3.1】的print_word函数是无参函数,它的定义中首句也可以写成:voidprint_word()//定义print_word()函数的首部;或:voidprint_word(void)//定义print_word()函数的首部【例3.1】的calc_sum函数是有参函数,不过它只有一个参数,参数的类型是整数类型。intcalc_sum(intn)//定义calc_sum()函数C++要求在定义函数时必须指定函数的类型。下面的函数f则有两个参数,第一个是整数类型,第二个是单精度实数类型,而函数的返回值是双精度实数类型:doublef(intx,floaty)//定义f()函数的首部(1)对库函数的声明其实,对库函数的声明语句已经写在有关包含文件中了,因此只要在程序文件头用include语句将这些包含文件包含到本程序中来,就完成了对库函数的声明。(2)对自定义函数的声明必须在调用某自定义函数的语句之前写上如下声明语句:函数类型关键字函数名([参数1类型,参数1名称][,参数2类型,参数2名称][…]);3.2.2函数的声明(2)对自定义函数的声明(续)也可以在声明语句中略去参数的名称,或写一个任意名称,这叫做函数原型(functionprototype),即声明函数原型。函数原型有下列两种表示形式:函数类型关键字函数名([参数1类型][,参数2类型][…]);函数类型关键字函数名([参数1类型,标识符1][,参数2类型,标识符2][…]);C++中的函数原型说明了函数的类型、函数名、函数各形式参数类型。使用函数原型是C和C++的一个重要特点。3.2.2函数的声明【例3.2】对被调函数做声明的示例。#includeiostream.h//*****ex3_2.cpp*****voidmain(){floatadd(floatx,floaty);//对add函数作声明floatsubtract(float,float);//对subtract函数作声明,用函数原型doublemultiply(floatp,floatq);//对multiply函数作声明,参数名任意floata,b,c1,c2;doublec3;coutpleaseinputa,b:;cinab;c1=add(a,b);c2=subtract(a,b);c3=multiply(a,b);coutc1,c2,c3endl;}}floatadd(floatx,floaty)//定义add函数{floatz;z=x+y;return(z);}floatsubtract(floatx,floaty)//定义subtract函数{floatz;z=x-y;return(z);}doublemultiply(floatx,floaty)//定义multiply函数{doublez;z=x*y;return(z);}运行情况如下:pleaseinputa,b:4.252.00↙6.25,2.25,8.5说明:(1)对函数的定义和函数声明是两回事,不要混淆。(2)之所以函数原型中可以省略形式参数的名称,是因为形式参数的名称是无关紧要的,且在调用前形参并不存在。(3)函数声明语句的位置。函数声明语句可以放在主调函数中,也可放在函数外面,只要出现在调用语句之前即声明有效。3.2.3函数的返回值(1)函数的返回值是通过函数中的return语句获得的。return语句将被调用函数中的一个确定值带回主调函数中去。return语句后面的括号可以要,也可以不要。return后面的值可以是一个表达式。(2)函数值的类型。既然函数有返回值,这个值当然应属于某一个确定的类型,应当在定义函数时指定函数值的类型。(3)如果函数值的类型和return语句中表达式的值不一致,则以函数类型为准,即函数类型决定返回值的类型。对数值型数据,可以自动进行类型转换。第(1)种形式是基本的形式。为了便于阅读程序,也允许在函数原型中加上参数名,就成了第(2)种形式。但编译系统并不检查参数名。因此参数名是什么都无所谓。上面程序中的声明也可以写成floatadd(floata,floatb);//参数名不用x、y,而用a、b效果完全相同。应当保证函数原型与函数首部写法上的一致,即函数类型、函数名、参数个数、参数类型和参数顺序必须相同。在函数调用时函数名、实参类型和实参个数应与函数原型一致。说明:(1)前面已说明,如果被调用函数的定义出现在主调函数之前,可以不必加以声明。因为编译系统已经事先知道了已定义的函数类型,会根据函数首部提供的信息对函数的调用作正确性检查。有经验的程序编制人员一般都把main函数写在最前面,这样对整个程序的结构和作用一目了然,统览全局,然后再具体了解各函数的细节。此外,用函数原型来声明函数,还能减少编写程序时可能出现的错误。由于函数声明的位置与函数调用语句的位置比较近,因此在写程序时便于就近参照函数原型来书写函数调用,不易出错。所以应养成对所有用到的函数作声明的习惯。这是保证程序正确性和可读性的重要环节。(2)函数声明的位置可以在调用函数所在的函数中,也可以在函数之外。如果函数声明放在函数的外部,在所有函数定义之前,则在各个主调函数中不必对所调用的函数再作声明。例如:charletter(char,char);//本行和以下两行函数声明在所有函数之前且在函数外部floatf(float,float);//因而作用域是整个文件inti(float,float);intmain(){…}//在main函数中不必对它所调用的函数作声明charletter(charc1,charc2)//定义letter函数{…}floatf(floatx,floaty)//定义f函数{…}inti(floatj,floatk)//定义i函数{…}如果一个函数被多个函数所调用,用这种方法比较好,不必在每个主调函数中重复声明。函数调用的一般形式:函数名([实际参数列表])如果是调用无参函数,则“实参表列”可以没有,但括号不能省略。如果实参表列包含多个实参,则各参数间用逗号隔开。实参与形参的个数应相等,类型应匹配(相同或赋值兼容)。实参与形参按顺序对应,一对一地传递数据。但应说明,如果实参表列包括多个实参,对实参求值的顺序并不是确定的。3.2.4函数的调用按函数在语句中的作用来分,可以有以下3种函数调用方式:1.函数语句把函数调用单独作为一个语句,并不要求函数带回一个值,只是要求函数完成一定的操作。如【例3.1】中的print_word()函数调用语句。2.函数表达式函数出现在一个表达式中,这时要求函数带回一个确定的值以参加表达式的运算。如c=2*max(a,b);3.函数参数函数调用作为一个函数的实参。如m=max(a,max(b,c));//max(b,c)是函数调用,其值作为外层max函数调用的一个实参函数调用的方式3.3函数的参数传递形参:在定义函数时函数名后面括号中的变量名称为形式参数(formalparameter),简称形参。形参是无内存单元(因而不存在)的任何合法标识符。实参:在调用一个函数时,调用语句的函数名后面括号中的参数称为实际参数(actualparameter),简称实参。实参是实际存在(因而有特定值)的常量、变量或表达式。【例3.3】形参和实参及其数据传递。#includeiostream//*****ex3_3.cpp*****usingnamespacestd;floatvolume(floatr,floath)//定义有参函数volume求圆柱体体积,r和h是形参{floatv;v=3.14*r*r*h;return(v);}voidmain(){floata,b,c;coutpleaseinputtwofloatnumbers:;cinab;c=volume(a,b);//调用函数volume,a和b是实参。函数值赋给变量ccoutThevolumeiscendl;}运行情况如下:pleaseinputtwofloatnukbers:2.05.0↙Thevolumeis62.8有关形参与实参的说明:(1)在定义函数时指定的形参,在未出现函数调用时,它们并不占内存中的存储单元,因此称它们是形式参数或虚拟参数,表示它们并不是实际存在的数据,只有在发生函数调用时,函数ma

1 / 111
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功