函数的相关概念
概念
函数是完成特定任务的独立程序代码单元
作用及功能
省去编写重复代码的麻烦,可以将一段经常需要使用的代码封装起来,在需要使用时可以直接调用,提高代码的可读性,更方便后期修改、完善
定义
指定名字,函数返回值类型,函数实现的功能,参数的个数与类型,以及函数应当完成什么操作(即函数的功能)
原型
函数声明给出了函数名、返回值类型、参数列表(重点是参数类型)等与该函数有关的信息
调用
使用已经定义好的函数。函数调用的一般形式为:functionName(param1, param2, param3 …); functionName 是函数名称,param1, param2, param3 …是实参列表。实参可以是常数、变量、表达式等,多个实参用逗号,分隔
虚参与实参
函数被调用时给出的参数包含了实实在在的数据,会被函数内部的代码使用,所以称为实际参数。在函数定义中出现的参数可以看做是一个占位符,它没有数据,只能等到函数被调用时接收传递进来的数据,所以称为形式参数
传值
把实参的值赋值给行参,相当于copy。那么对行参的修改,不会影响实参的值
传地址
实际是传值的一种特殊方式,不过传递的是地址,不是普通的赋值,那么传地址以后,实参和行参都指向同一个对象,因此对形参的修改会影响到实参
变量的作用域与生存期
作用域是指可以存取变量的代码范围,生存期是指可以存取变量的时间范围
如何确定代码中的一个标识符是函数?
标识符后跟小括号“(”
调用函数后如何回到调用点?
如函数A调用函数B,进入函数B前将函数A的当前状态保存起来(包括函数A的所有局部变量值、调用点–称为断点–等进行压栈),函数B执行完成后将函数A的状态恢复(出栈),然后从断点处继续执行函数A;
简单理解:相当于每次调用函数,系统都帮你记住了断点处的状态,调用完成后,帮你从断点处继续执行;即使嵌套调用很多次,都不会出错。除非栈的内存开销超出了承受范围
如何设计一个函数?
- 首先要明确函数的功能,并给函数命名,命名要反映出函数的功能
- 然后确定函数的虚参和返回值,并根据函数功能决定虚参是采用传值还是传地址
案例:输入两个整数,要求用函数找到较大数
- 函数名:定名为max
- 函数类型:整型
- max函数应当有两个参数,参数类型为整型
编写程序:先编写max函数
int max(int x,int y)
{
int z;
z = x>y?x:y;
return(z);
}
再编写主函数
int main()
{
int max(int x,int y);
int a,b,c;
printf("请输入两个数:");
scanf_s("%d%d,&a,&b);
c=max(a,b);
printf("max is %d\n",c);
return 0;
}
变量的作用域、生存期与函数的独立性
根据变量声明时的位置,可将其分为全局变量和局部变量。
全局变量(global) 也称为外部变量,它是在函数外部定义的变量。它不属于哪一个函数,它属于一个源程序文件,其作用域是整个源程序。程序中所有未再次被声明的名字都会被认为是全局声明中的名字。
局部变量(local) 也称为内部变量,它是在函数内部定义说明的。其作用域仅限于函数内,即其所在的花括号{…}内,离开该函数后再使用这种变量是非法的。
生存期即变量值存在的时间,可以分为静态存储方式和动态存储方式。可见生存期只是和变量存储的位置相关。
静态存储(static) 全局变量即属于静态存储,通常是由编译器在编译时分配分定存储单元(静态存储区)并一直保持不变,在函数调用结束后不消失而保留原值,生存期为整个程序运行过程。
动态存储(auto) 函数中的形参和在函数中定义的变量(包括在复合语句中定义的变量),如不专门声明为 static 存储类别,都属动态存储,都是系统在运行时动态地分配存储空间的,数据存储在动态存储区(栈区)中,在函数调用结束时就自动释放这些存储空间。
编写函数的实现代码时,除了使用虚参和局部变量外,尽量不要使用全局变量、不要使用局部static静态变量,以提高函数的独立性(独立性高意味着程序的可读性和可维护性好)
递归函数
概念
直接或间接地调用函数本身
设计与编程
找出递归公式,必须是降阶公式,且有终止递归的条件。按照公式直接编码
递归的内部执行过程
采用函数调用时的状态保存和恢复技术
案例:用递归法将一个整数n转换成字符串。例如,输入483,应输出字符串“483”。n的位数不确定,可以是任意位数的整数
#include"pch.h"
#include<iostream>
void convert(int n)
{
int i;
if((i=/10)!=0)
convert(i);
putchar(n%10+'0');
}