分类: C/C++
2015-05-02 16:32:03
一、为什么要用函数
1、 函数:从本质意义上来说,函数就是用来完成一定的功能的。所谓函数名就是给该 功能起一个名字,如果该功能是用来实现数学运算的,就是数学函数。
2、 实例:想输出以下的结果,用函数调用实现
******************
How do you do!
******************
解题思路:在输出的文字上下分别有一行“*”号,显然不必重复写这段代码,用一个函数print_star来实现输出一行“*”号的功能。再写一个print_message函数来输出中间一行文字信息,用主函数分别调用这两个函数即可。
编写程序:
#include
int main()
{
void print_star(); //声明print_star函数
void print_message(); //声明print_ message函数
print_star(); //调用print_star函数
print_message(); //print_message函数
print_star(); //调用print_star函数
return 0;
}
void print_star() //定义print_star函数
{
printf(“******************\n”); //输出一行*号
}
void print_message() //定义print_message函数
{
printf(“How do you do!\n”); //输出一行文字信息
}
运行结果:
******************
How do you do!
******************
二、怎样定义函数
1、 为什么要定义函数
定义函数应包括以下几条内容:
1) 指定函数的名字,以便以后按名调用。
2) 指定函数的类型,即函数返回值的类型。
3) 指定函数的参数的名字和类型,以便在调用函数时向它们传递数据。对无参数不需要这项。
4) 指定函数应当完成什么操作,也就是函数是做什么的,即函数的功能。这是最重要的,是在函数体中解决的。
2、 定义函数的方法
1) 定义无参函数的一般形式为
类型名 函数名()
{
函数体
}
或
类型名 函数名(void)
{
函数体
}
函数名后面括号内的void表示“空”,即函数没有参数。
函数体包括声明部分和语句部分。
1) 定义有参函数的一般形式为
类型名 函数名(形式参数表列)
{
函数体
}
2) 定义空函数
在程序设计中有时会用到空函数,它的形式为
类型名 函数名()
{
}
3、 调用函数
1) 函数调用的一般形式为
函数名(实参表列)
a) 函数调用语句
把函数调用单独作为一个语句。如上例中的“print_star();”这时不要求函数带回值,只要求函数完成一定的操作。
b) 函数表达式
函数调用出现在另一个表达式中,如“c = max(a, b);”,max(a, b)是一次赋值表达式中的一部分。这时要求函数带回一个确定的值以参加表达式的运算。例如:
c = 2 * max(a, b);
c) 函数参数
函数调用作为另一个函数调用时的参数。例如:
m = max(a, max(b, c));
2) 函数调用时的数据传递
a) 形式参数和实际参数
在调用有参函数时,主调函数和被调函数之间有数据传递关系。
在定义函数时函数名后面括号中的变量名称为“形式参数”(简称“形参”)或“虚拟参数”。
在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数”(简称“实参”)。实际参数可以是常量、变量或表达式。
b) 实参和形参间的数据传递
在调用函数过程中发生的实参与形参间的数据传递,常称为“虚实结合”。
3) 函数调用的过程
a) 在定义函数中指定的形参,在未出现函数调用时,它们并不占内存中的存储单元。在发生函数调用时,函数max的形参被临时分配内存单元。
b) 将实参对应的值传递给形参。
c) 在执行max函数期间,由于形参已经有值,就可以利用形参进行有关的运算。
d) 通过return语句将函数值带回到主调函数。
e) 调用结束,形参单元被释放。注意:实参单元仍保留并维持原值,没有改变。如果在执行一个被调用函数时,形参的值发生改变,不会改变主调函数的实参的值。
4) 函数的返回值
a) 函数的返回值是通过函数中的return语句获得的。
b) 函数值的类型。
c) 在定义函数时指定的函数类型一般应该和return语句中的表达式类型一致。
4、 对被调用函数的声明和函数原型
1) 在一个函数中调用另一个函数(即被调用函数)需要具备如下条件:
a) 首先被调用的函数必须是已经定义的函数(是库函数或用户自己定义的函数。)
b) 如果使用库函数,应该在本头文件开头用#include指令将调用有关库函数时所需用到的信息“包含”到本头文件中来。
c) 如果使用用户自己定义的函数,而该函数的位置在调用它的函数(即主调函数)的后面(在用一个文件中),应该在主调函数中对被调用的函数作声明。
2) 函数原型的一般形式有两种:
a) 参数类型 函数名(参数类型1 参数名1, 参数类型2 参数名2,…, 参数类型n 参数名n);
b) 参数类型 函数名(参数类型1, 参数类型2,…, 参数类型n);
5、 函数的嵌套调用
C语言的函数定义是相互平行、独立的,也就是说,在定义函数时,一个函数内不能再定义另一个函数,也就是不能嵌套定义,但可以嵌套调用函数,也就是说,在调用一个函数的过程中,又调用另一个函数。
6、 函数的递归调用
在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。
7、 数组作为函数参数
1) 数组元素作函数实参
数组元素可以用作函数实参,不能用作形参。因为形参是在函数被调用时临时分配存储单元的,不可能为一个数组元素单独分配存储单元(数组是一个整体,在内存中占连续的一段存储单元)。在数组元素作函数实参时,把实参的值传给形参,是“值传递”方式。数据传递的方向是从实参传到形参,单向传递。
2) 数组名作函数参数
除了可以用数组元素作为函数参数外,还可以用数组名作函数参数(包括实参和形参)。应当注意的是:用数组元素作实参时,向形参变量传递的是数组元素的值,而用数组名作函数实参时,向形参(数组名或指针变量)传递的是数组首元素的地址。
3) 多维数组名作函数参数
可以用多维数组名作为函数的实参和形参,在被调用函数中对形参数组定义时可以指定每一维的大小,也可以省略第一维的大小说明。
8、 局部变量和全局变量
1) 局部变量
定义变量可能有3种情况:
a) 在函数的开头定义;
b) 在函数内的复合语句内定义;
c) 在函数的外部定义;
在一个函数内部定义的变量只在本函数范围内有效,也就是说只有在本函数内
才能引用它们,在此函数以外是不能使用这些变量的。在复合语句内定义的变量只在本复合语句范围内有效,只有在本复合语句内才能使用它们。在该复合语句以外是不能使用这些变量的,以上这些称为“局部变量”。
2) 全局变量
在函数内定义的变量是局部变量,而在函数之外定义的变量称为外部变量,外
部变量是全局变量(也称全程变量)。全局变量可以作为本文件中其他函数所共用。它的有效范围从定义变量的位置开始到本源文件结束。
9、 变量的存储方式和生存期
1) 动态存储方式与静态存储方式
从变量的作用域(即从空间)的角度来观察,变量可以分为全局变量和局部变
量。
还可以从另一角度,即从变量值存在的时间(即生存期)来观察。
变量的存储有两种不同的方式:静态存储方式和动态存储方式。静态存储方式是指在程序运行期间由系统分配固定的存储空间的方式,而动态存储方式则是在程序运行期间根据需要进行动态的分配存储空间的方式。
在动态存储区中存放以下数据:
a) 函数形式参数。在调用函数时给形参分配存储空间。
b) 函数中定义的没有用关键字static声明的变量,即自动变量。
c) 函数调用时的现场保护和返回地址等。
2) 局部变量的存储类别
a) 自动变量(auto变量)
b) 静态局部变量(static局部变量)
c) 寄存器变量(register变量)
3) 全局变量的存储类别
一般来说,外部变量是在函数的外部定义的全局变量,它的作用域是从变量的
定义处开始,到本程序文件的末尾。在此作用域内,全局变量可以为程序中各个函数所引用。但有时程序设计员希望能扩展外部变量的的作用域。有以下几种情况:
a) 在一个文件内扩展外部变量的作用域
外部变量声明(extern)
b) 将外部变量的作用域扩展到其他文件
c) 将外部变量的作用域限制在本文件中
4) 存储类别小结
对一个数据的定义,需要指定两种属性:数据类型和存储类别。
下面从不同角度做些归纳:
a) 从作用域角度分,有局部变量和全局变量。它们采用的存储类别如下:
自动变量,即动态局部变量(离开函数,值就消失)
局部变量 静态局部变量(离开函数,值仍保留
寄存器变量(离开函数,值就消失)
按作用域 (形式参数可以定义为自动变量或寄存器变量)
角度分
静态外部变量(只限本文件引用)
全局变量 外部变量(即非静态的外部变量,允许其他文件使用)
b) 从变量存在的时间(生存期)来区分,有动态存储和静态存储两种类型。静态存储是程序整个运行时间都存在,而动态存储则是在调用函数时临时分配单元。
自动变量(本函数内又效)
动态存储 存储器变量(本函数内又效)
形式参数(本函数内又效)
按变量的生存期分
静态局部变量(函数内有效)
静态存储 静态外部变量(本文件内有效)
外部变量(用extern声明后,其他文件可
引用)
c) 从变量值存放的位置来区分,可分为:
静态局部变量
内存中静态存储区 静态外部变量(函数外部静态变量)
按变量值存 外部变量(可为其他文件引用)
放的位置分 内存中动态存储区:自动变量和形式参数
CPU中的寄存器:寄存器变量
d) 关于作用域和生存期的概念
如果一个变量在某个文件或函数范围内是有效的,就称该范围为
该变量的作用域。在此作用域内可以引用该变量,在专业书中称变量在此作用域内“可见“,这种性质称为变量的可见性。如果一个变量值在某一时刻是存在的,则认为这一时刻属于该变量的生存期,或称该变量在此时刻“存在”。
10、关于变量的声明和定义
一个函数一般由两部分组成:声明部分和执行语句。
对变量而言,声明与定义的关系稍微复杂一些。在声明部分出现的变量有两种情况:一种是需要建立存储空间的,另一种是不需要建立存储空间的。前者称为定义性说明,或简称定义;后者称为引用性声明。
一般来说,把建立存储空间的声明称定义,而把不需要建立存储空间的声明称为声明。
11、内部函数和外部函数
1)内部函数:如果一个函数只能被本文件中其他函数所调用。
在定义内部函数时,在函数名和函数类型的前面加static,即:
static 类型名 函数名(形参表);
2)外部函数:如果在定义函数时,在函数首部的最左端加关键字extern,则此函数是外部函数。可供其他文件使用。