函数组成:
返回类型 函数名(函数参数)
{
语句项
}
函数参数
实际参数:
真实传给函数的参数,可以是:常量、变量、表达式、函数等。在进行函数调用时,实参必须有确定值,把这些值传送给形参
形式参数:
形式参数是指函数名后括号中的变量,形式参数只有在函数被调用的过程中才实例化(分配内存单元),实例化后相当于实参的一份临时拷贝,当函数调用完成之后形式参数就自动销毁了
函数的调用
传值调用:
函数形参和实参地址不同,因此形参被修改并不会影响实参
传址调用:
把函数外部创建变量的地址传给函数参数,通过直接访问地址对变量进行修改,达到函数内部直接操作函数外部变量的效果
代码:
#include<stdio.h>
void SwapV1(int ca, int cb)
{
int temp = ca;
ca = cb;
cb = temp;
}
void SwapV2(int* pa, int* pb)
{
int temp = *pa;
*pa = *pb;
*pb = temp;
}
int main()
{
int a = 5;
int b = 10;
//传值调用
SwapV1(a, b);
printf("V1:a = %d,b = %d\n", a, b);
//传址调用
SwapV2(&a, &b);
printf("V2:a = %d,b = %d\n", a, b);
return 0;
}
运行结果:
嵌套调用
函数之间可以嵌套调用,即在函数内部调用其它函数,如上述代码中在main函数中调用Swap1,Swap2函数
注:函数之间可以嵌套调用但不可以嵌套定义
链式访问
把一个函数的返回值作为另一个函数的参数
有如下代码:
#include<stdio.h>
int main()
{
printf("%d", printf("%d", printf("%d", 28)));
return 0;
}
这里我们需要了解printf函数的返回值
如果成功,返回值是写入的字符总数
如果写入错误,设置错误指示器(ferror函数值为假),并返回一个负数
运行结果:
函数声明
返回类型 函数名(函数参数);
函数参数可以只写参数类型,不写参数名
规定函数必须先声明后使用,但C语言中如果直接使用没声明也可以通过,但是会有警告
#include<stdio.h>
//int Add(int, int);
int main()
{
int a = 10;
int b = 5;
int ret = Add(a, b);
printf("%d\n", ret);
return 0;
}
int Add(int a, int b)
{
int z = a + b;
return z;
}
函数声明一般放在头文件中,如果我们只想让他人知道函数如何使用,却不知道实现函数的源代码,方法如下:
此时文件路径下会生成一个.lib文件,这个文件是看不到源码的
将add.h文件和Add.lib文件都给test
添加现有项add.h文件到头文件,最后得到结果
函数递归
递归函数是直接或间接调用自身的函数
递归的两个必要条件:(防止无限递归下去)
存在限制条件,当满足这个限制条件的时候,递归便不再继续
每次递归调用之后越来越接近这个限制条件
例:编写函数不允许创建临时变量,求字符串的长度
代码如下:
#include<stdio.h>
int my_strlen(const char* str)
{
if (*str == '\0')
{
return 0;
}
else return 1 + my_strlen(str + 1);
}
int main()
{
char* p = "abcd";
int len = my_strlen(p);
printf("%d\n", len);
return 0;
}
图解:
递归与迭代
求第n个斐波那契数
递归:
#include<stdio.h>
int Fib(int n)
{
if (n <= 2)
{
return 1;
}
else
{
return Fib(n - 2) + Fib(n - 1);
}
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fib(n);
printf("%d\n", ret);
}
运行结果:
当计算第50个斐波那契数的时候,需要的时间就已经很长很长了,因为这种递归做法计算机需要进行很多重复计算,如我们递归到Fib(20)时,还需要向下计算Fib(19)+Fib(18),而每一个分支又要向下进行许多重复计算,显然计算斐波那契数时用递归不是很合适。
迭代:
#include<stdio.h>
long long Fib(int n)
{
long long a = 1;
long long b = 1;
long long c = 1;
//当n为1或2时,斐波那契数都为1
while (n > 2)
{
c = a + b;
a = b;
b = c;
n--;
}
return c;
}
int main()
{
int n = 0;
scanf("%d", &n);
long long ret = Fib(n);
printf("%lld\n", ret);
}
运行结果:
如阶乘,斐波那契等问题都有相应的递归公式,这种公式便于理解,然而事实上这些问题用递归可能并不是很合适,那么我们就需要迭代,用递归一定要保证没有错误的测试用例,如果不能保证,则不要使用