一、函数的概念 在第一章中我们提到,C语言编写的程序都是由函数构成。在C语言程序文件中至少要有一个函数,也可以有多个函数。其中,有并且只能有一个main函数。程序的执行都是从main函数开始,并执行到main函数中的最后一条语句结束。 那么到底什么是函数?为什么C语言中要把程序代码写在函数中来表示?函数的作用又是什么那?下面我们用生活中的实例来帮助理解函数的概念。 假设我们家里要装修,那么就有很多工作要做。如,打家具、贴瓷砖、刷油等。而这些工作要由谁来完成呢?是我们自己来完成,我们来学习这些工种吗?还是请一个人来做,他来完成所有工种?还是,由不同的人来完成不同的工作呢?实际情况是:由木匠来完成打家具的工作;由瓦匠来完成贴瓷砖的工作;由油匠来完成刷油的工作。如图1所示。图中的房主就相当于我们的main函数,木匠和油匠,相当于C程序中两个具有特定功能的函数。这样做的好处是显而易见的:如果由我们自己来完成,由于我们不是专业人士,我们每家每户都要重复的去学习装修技术,我们需要付出几倍的工作量,也不一定得到专业的质量;如果所有工作都由一个人来完成,他在某一个工种上不一定能做到最大的精确;如果由不同的人来完成,由于他只专心于某一专业,可以做到精益求精。显然,这样的社会分工是合理的、高效的。 
图1家庭装修工作分工 |
下面我们再来说编程。假设我们要做一个学生成绩管理的程序。这里面,我们也有很多工作要做。如,查找学生的成绩、删除学生的成绩、添加学生的成绩、计算学生的成绩等等。如果我们把所有的程序功能都写在main函数中,如果其他程序也要设计这些功能的话,必须重新、重复编写这些代码。在程序结构上,代码都写在一个函数中,程序的可读性、可理解性都会大大降低。我们通常的解决办法是:把一个大系统功能分解为若干的小系统功能,小系统功能再进一步分解成更小的系统功能,这就是程序的模块化思想。而在C语言中,将每个功能模块对应成一个函数。C语言程序就是由各式各样的函数构成的。采用函数的好处是:程序结构清晰, 便于理解和阅读;函数调用灵活,只要需要使用该功能的地方,就可以调用这个函数,减少了代码的重复编写。如图2所示。 
图 2 学生成绩管理模块 进一步说,函数(Function)是一系列独立的程序步骤,将这些程序步骤集合在一起,并赋予一个名字,就形成了一个函数。二、函数的定义 所谓函数的定义,也就是构造一个函数。那么要构造一个正确的函数,首先就要了解函数的结构,然后根据函数的结构,来设计函数。 1. 首先我们就从我们最先认识的main函数来开始认识函数的结构。 main函数的结构如下面代码所示,其中:
void main() { } void为函数类型; main为函数名; ()中可以放函数的参数,此处没有参数; {}中为函数体。
2. 根据一个函数的名字后面的括号中有没有参数,可以对函数进行分类,如图3所示。 
图3 函数的构成 |
图中,左右两部分表示的两种不同类型的函数的结构。比较左右两部分,右边函数的函数名后面的括号中含有参数,我们将这样的函数称之为“有参函数”;相反,左边的函数的函数名后面的括号中不含参数,我们将这样的函数称之为“无参函数”; 3.不管是有参函数还是无参函数,函数的组成都包括:函数的首部(head)+函数体(body)。如图3所示。 4. 函数的首部又包括:函数的类型,函数名,函数的参数。(注意:函数名后面的一对小括号()不能省略) 5.函数体是函数为实现其功能而设计的语句。 6.总的说来,函数由4个部分构成:函数类型、函数名、函数参数、函数体。下面我们简单解释每一部分的含义: 函数类型:表示函数是否带回一个返回值,如果有,函数类型尽量与返回值类型一致;如果没有返回值,函数类型则定义为“void”类型。 函数名:是一个标识符,用以区分不同的函数。同时,函数名也是函数的入口地址,即首地址。函数名的命名规则同其他标识符,即由数字,字母,下划线构成,其中数字不能开头。建议,函数名字可以体现函数功能。 函数参数:函数的参数是函数之间消息传递的接口。一个函数可以有参数,这样就要求调用它的函数,必须给它的参数传递具体的取值;一个函数也可以没有参数,这样调用它的函数,就无须提供任何数值,就可以调用该函数。 函数体:函数体由一对花括号(“{”、“}”)为定界符。花括号中可以有若干条语句。这些语句用以实现函数的特定功能。 7. 综上所述,如果要构造一个函数,只要准确的设计出:函数类型,函数名,函数参数,函数体,即完成了函数的定义。 8. 任何一个函数的定义都要独立于其他函数,即不可以在一个函数体内来定义一个函数(函数不可以嵌套定义)。 三、函数的声明 由案例1可知,当被调函数书写在主调函数之后的时候,主调函数直接调用它,编译程序时会出现一个错误,解决的办法是,将被调函数移动到主调函数之前,这样程序就可以顺利执行。调整被调函数位置的目的是为了通知编译系统了解被调函数的属性特征,以便在主调函数调用它的时候,验证调用是否正确合法。如,有无返回值?有无参数?参数类型?等等。 我们假设在一个C程序文件中有多个函数。而函数之间存在很复杂的调用关系,这时候,如果我们依靠调整函数书写位置来保证所有的被调函数都书写在主调函数之前,这将是一件很复杂的工作,并且也许是不可完成的工作。那么如何解决这个问题,让程序员不必为函数的书写位置烦恼?这就是本节要讨论的问题,“函数声明”。 如果我们在程序的开头对所有程序中定义的函数进行声明的话,那么这些函数的书写位置就不受任何限制,可以任意书写。那么,如何进行函数声明那? 前面我们介绍过函数的类型有两种:库函数和自定义函数。那么函数的声明也分这两种来讨论。函数的声明只要将函数的首部给出,编译系统就可以了解被调函数的一些信息:有无返回值,返回值类型,有无参数,参数个数,参数类型。这样编译器就可以检查,主调函数中函数调用是否正确。 1、库函数的声明 对于库函数,为了简化程序员的工作,各种C系统都根据库函数的功能将其分类,如,开方,三角函数等归类为数学函数;printf和scanf归类为基本输入和输出函数。然后将这一类函数的声明都写入到一个文件中,如开方函数(sqrt)的声明就在文件“math.h”中。其中math表示“数学”,扩展名“h”,是head的缩写,意思是“头”,我们把扩展名为“h”的这些文件统称为“头文件”。在比如printf函数所在的头文件为“stdio.h”(标准输入输出)中。如果你在程序中使用了某个库函数,为了能够正确调用这个函数,就需要用“#include”来包含这个函数所在的头文件,来对这个函数进行声明。其中头文件要用一对尖括号<>或一对双引号“”括起来。例如: #include<stdio.h>(标准输入输出函数头文件) #include<math.h>(数学函数头文件) #include<string.h>(字符串处理函数头文件)
2、自定义函数的声明
|