一、函数概述
1、C语言的函数。C语言的函数是子程序的总称,包括函数和过程。
C语言函数可以分为库函数、用户自定义函数
2、C语言的程序由函数组成,函数是C语言程序的基本单位,程序的总体功能通过函数的调用来实现。其中,main起点。
3、函数的一些概念:主函数、其它函数;主调函数、被调函数;库函数、用户自定义函数;无参函数、有参函数;无返回值函数、有返回值函数
二、函数的一般形式-函数应当先定义,后调用。
1、函数定义的一般形式及说明
任何函数都是由函数说明和函数体两部分组成的。函数说明包括:函数类型,函数名,函数参数;函数功能的实现代码写在函数体中。根据函数有无参数,可以把函数分为无参函数和有参函数。
(1)无参函数定义的一般形式
定义无参函数的一般形式为:
【函数类型】 函数名( )
{
声明语句部分
可执行语句部分
}
(2)有参函数定义的一般形式
定义有参函数的一般形式为:
【函数类型】 函数名( 数据类型 参数【,数据类型 参数2…】)
{
声明语句部分
可执行语句部分
}
(3)空函数
【函数类型】 函数名()
{ }
三、函数的参数和返回值
1 形式参数和实际参数
函数的参数分为形参和实参两种。形参出现在函数定义中,在整个函数体内都可以使用,离开该函数则不能使用。实参出现在主调函数中,进入被调函数后,实参变量也不能使用。形参和实参的功能是作数据传送。发生函数调用时,主调函数把实参的值传送给被调函数的形参从而实现主调函数向被调函数的数据传送。
函数的形参和实参具有以下特点:
1.形参变量只有在被调用时才分配内存单元,在调用结束时,所分配的内存单元也将被释放。因此,形参只有在函数内部有效。函数调用结束返回主调函数后则不能再使用该形参变量。
2.实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。因此应预先用赋值、输入等办法使实参获得确定值。
3.实参和形参在数量上,类型上,顺序上应严格一致,否则会发生类型不匹配的错误。
4.函数调用中发生的数据传送是单向的。即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化
2 函数的返回值
函数的返回值是指函数被调用之后,执行函数体中的程序段所取得的并通过return语句返回给主调函数的值。
四、 函数调用
1 函数调用的一般形式
函数调用的一般形式为:
函数名(实参列表);
如果调用无参函数,则”实参列表”是空的,但括号不能省略。如果实参列表包含多个实参,则各参数间用逗号隔开。实参和形参的个数应相等,类型应匹配。实参与形参按顺序对应,一一传递数据。当实参列表包括多个值时,对实参求值的顺序并不确定。有的系统按自左向右求实参的值,有的则按自右向左的顺序。要注意的是,visual c++ 6.0编译器是按自右向左的顺序求实参列表的值的。
2 函数调用的方式
按函数在程序中出现的位置来分,可以有一下三种函数调用的方式。
1. 函数语句
把函数调用作为一个语句。如printstart();这时不要求函数带返回值,只要求函数完成一些操作。
2. 函数表达式
函数出现在一个表达式中,这种表达式称为函数表达式。这时要求函数带回一个确定的值以参加表达式的运算。例如:
s=sum(a,b)+sum(x,y);
函数sum是表达式的一部分,将sum(a,b)的值加上sum(x,y)的和赋值给s。
3. 函数参数
函数调用作为一个函数的参数,例如:
s=sum(a,sum(b,c));
其中,sum(b,c)是一次函数调用,它的值作为sum另一次调用的参数。s的值为a,b,c三个的总和。
其实,函数调用作为函数的参数,也是函数表达式调用的一种形式,因为函数参数本身就是一个表达式的形式。
3 对被调用函数的声明和函数原型
如果一个函数要调用另外一个函数,首先是被调用的函数必须存在。其次还应在主调函数中对所有被调函数加以说明,否则,在连接时会出现找不到所调用函数的错误信息。同变量一样,函数的调用也应遵循“先定义后使用”的原则。
五、函数的嵌套调用和递归调用
(1)函数的嵌套调用说明
一般地说,函数的嵌套调用是指,在执行被调用函数时,该函数又调用其它函数的情形。
C语言中不允许作嵌套的函数定义。因此各函数之间是平行的,不存在上一级函数和下一级函数的问题。但是C语言允许在一个函数的定义中出现对另一个函数的调用。这样就出现了函数的嵌套调用。即在被调函数中又调用其它函数。这与其它语言的子程序嵌套的情形是类似的。
注意:被调用函数执行完毕后,将返回到调用函数的断点继续执行。
简言之,谁调用,返回到谁的断点继续执行。
(2)函数的递归调用说明
一个函数在它的函数体内调用它自身称为递归调用。这种函数称为递归函数。C语言允许函数的递归调用。在递归调用中,主调函数又是被调函数。执行递归函数将反复调用其自身,每调用一次就进入新的一层。
以下为补充内容:
一、内部函数和外部函数
1 内部函数
一个函数如果只能被本文件中其它函数所调用,称为内部函数。内部函数又称静态函数。在定义内部函数时在函数名和函数类型前面加static。即:
static 函数类型 函数名(形参列表)
{
函数体
}
例:static int fun(int a,int b)
特点:只能被本文件中的函数所调用。
好处:不用担心与其它源文件中的函数同名,因为即使同名也没关系。
2 外部函数
一个函数可以被其它文件中其它函数所调用,它称为外部函数。在定义函数时可冠以关键字extern(省略也可),表示此函数是外部函数。即:
extern 函数类型 函数名(形参列表)
{
函数体
}
如:extern int fun(int a,intb)
特点:允许被所有源文件中的函数所调用。
注意:调用其它源文件中的外部函数时,需要对其进行说明
3 多个源文件的编译与连接
在软件工程项目中,采用结构化方法进行程序设计与编程,通常会产生多个源文件(例如源程序文件、数据结构定义文件等)。
那么,如何将这些源文件编译、连接成一个统一的可执行文件呢?
一般有两种方法:
1. 分别编译、一并连接
C编译程序是以源文件为编译单位。
当一个程序中的函数和数据结构分放在多个源文件中时:先将各文件分别编译,再通过link命令产生一个可执行文件(.exe) 。
2. 集中编译、连接
利用编译预处理命令#include,将其它源文件包含到主函数main( )所在的源文件的开头;然后直接编译该文件即可。
二、变量的作用域
1 局部变量
局部变量也称为内部变量。局部变量是在函数内(包括函数说明和函数体)作定义说明的。其作用域仅限于函数内, 离开该函数后再使用这种变量是非法的。
2 全局变量
全局变量也称为外部变量,它是在函数外部定义的变量。它不属于哪一个函数,它属于一个源程序文件。其作用域是整个源程序。在函数中使用全局变量,一般应作全局变量说明。只有在函数内经过说明的全局变量才能使用。全局变量的说明符为extern。但在一个函数之前定义的全局变量,在该函数内使用可不再加以说明。
三、变量的存储类别
1 动态存储和静态存储
C语言中的变量,不仅有类型特性,还有存储特性,从变量值存在的时间(即生存期)角度来分,可以分为静态存储方式和动态存储方式。:
(1).动态存储方式:是在程序运行期间根据需要进行动态的分配存储空间的方式。
自动内部变量(auto)、寄存器变量(register)
(2).静态存储方式:是指在程序运行期间分配固定的存储空间的方式。静态内部变量(static)、外部变量(extern)
为了提高效率,C语言允许将局部变量得值放在CPU中的寄存器中,这种变量叫“寄存器变量”,用关键字register作声明。
(4).文件级外部变量和程序级外部变量
前面介绍过,在函数外部定义的变量称为外部变量。如果一个程序由多个源文件构成,根据某个源文件中定义的外部变量能否被其它源文件中的函数所引用,将外部变量分为两个作用域级别:
1. 文件级外部变量──只允许被本源文件中的函数引用,其定义方式如下:
static 数据类型 外部变量表;
2. 程序级外部变量──允许被程序中各源文件内的函数引用,其定义方式如下:
extern 数据类型 外部变量表;
同一程序中的其它源文件内的函数如果想引用程序级外部变量时,需要对其进行说明。
有效范围:从定义变量的位置开始到本源文件结束,及有extern说明的其它源文件。
注意:
1)extern不是变量定义,但可扩展外部变量作用域。
2)若外部变量与局部变量同名,则外部变量被屏蔽。

