1.函数的定义
函数:为了实现特定功能的独立代码模块;
库函数:
scanf() printf() strlen() strcat().....
函数的一般形式:
<数据类型> <函数名> (形式参数说明)
{
函数体;
return (表达式);
}
数据类型:和返回值保持一致,没有返回值数据类型为void;
函数名:
是一个合法的标识符;
函数名也是函数的入口地址;
形式参数说明:
简称形参,可以有多个形参也可以没有,如果有多个参数用 ','隔开;
作用:告诉函数调用者,在调用函数的时候确定传递的参数的类型;
函数体:可以为大于等于0条语句;
return: 作为返回值,和数据类型保持一致,数据为void没有返回值,
可以写return 或者不写;
2.函数的调用
函数名(实际参数);
eg:
char ch = getchar();
3.函数的说明
<数据类型> <函数名> (形式参数说明);
在说明函数的时候可以只写形参的类型;
4.函数的传参
函数传参的实质:
将实参作为形参的初始化;
① 全局变量
② 复制传递
将实参的值复制给形参,形参不能修改实参的值;
eg:
int a = 10, b = 20;
int ret = addFunc(a, b);
③ 地址传递
将实参的地址传递给形参,形参可以修改实参的值;
eg:
int a, b;
myswap(&a, &b);
5.数组作为参数传递
数组的传参:
复制传递:
eg:
testArray(arr, 5);
函数原型:
int testArray(int p[], 5);
//sizeof(p) == 8 ; //64位操作系统
地址传递:
eg:
testArray(arr, 5);
函数原型:
int testArray(int *p, 5);
总结:复制和地址传递,实质上都是将数组的首地址赋值给一个指针
变量,只是形参的表现形式不同;
数组再传递参数的时候一般都需要传数组的长度;
二维数组的传参:
函数原型:
//传第一个元素的地址(一级指针)
int testArray(int *p, int n);
//传数组首地址(行地址)
int testarray(int i, int (*p)[3]);
// int testarry(int i, int j, int (*p)[j]);//不规范
指针数组传参:
char buf[5][32] = {"hello", "world", "A", "how",
"4321"};
char *pbuf[5] = {buf[0], buf[1], buf[2], buf[3],
buf[4]};
按照大小,给指针数组里面的字符串排序;
指针数组传参的时候实参需要传递,指针数组首地址和指针数组大小;
(形参需要用二级指针);
6.指针函数
返回值为一个地址的函数;
一般形式:
《数据类型》* 《函数名》(形参)
{
函数体;
return 地址量;
}
7.函数指针
本质是一个指针:
一般形式:
<数据类型>(*函数指针名)(形式参数说明)
数据类型和函数指针指向的函数返回值保持一致;
形式参数说明: 和函数指针指向的函数的形参保持一致;
8.函数指针数组
本质是一个数组,数组里存放的是函数指针;
一般形式:
数据类型 (*函数指针数组名[元素个数])(形式参数说明);
9.递归函数
一个直接或者间接调用自己的函数;
递归函数调用的执行过程分为两个阶段:
递推阶段:
从原问题出发,按递归公式递推从未知到已知,最终达到递归终止条
件。
回归阶段:
按递归终止条件求出结果,逆向逐步代入递归公式,回归到原问题求
解。
阶乘;
n! = n * (n-1) *(n-2) *(n-(n-1))