一、函数是什么
函数是一组一起执行一个任务的语句。每个 C 程序都至少有一个函数,即主函数 main() ,所有简单的程序都可以定义其他额外的函数。
我们可以把代码划分到不同的函数中。如何划分代码到不同的函数中是由我们自己来决定的,但在逻辑上,划分通常是根据每个函数执行一个特定的任务来进行的。
函数还有很多叫法,比如方法、子例程或程序,等等。
二、函数中的分类
1.库函数
由C语言提供给我们使用的函数
为什么要有库函数?
在我们的编程过程中,有许多功能是会频繁使用到的,例如:打印(printf)、对字符进行拷贝(strcpy)等等。
但是这些功能都比较基础,并不是业务性的代码,为了提高开发效率,C语言的基础库中给给程序员们提供了一系列的库函数,方便程序员们使用。
2.自定义函数
由程序员自己定义的函数
基本结构如下:
ret_type fun_name(para1, * )
{
statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1 函数参数
示例:
写一个函数,返回两个数中的较大值
#include<stdio.h>
/* 函数返回两个数中较大的那个数 */
int max(int num1, int num2)
{
/* 局部变量声明 */
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int c = max(a, b);
printf("%d", c);
return 0;
}
代码结果:
三、函数的参数
1.实际参数(实参)
实参是真实传给函数的参数。
实参可以是:常量、变量、表达式、函数等。
无论实参是何种形式的量,在进行函数调用的时候,都必须有确定的值,以便把这些值传给形参。
2.形式参数(形参)
形参是指函数名后括号中的变量。
形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁。
形参其实就是实参的一份临时拷贝。
四、函数的调用
1.传值调用
该方法把参数的实际值复制给函数的形式参数。在这种情况下,函数的实参和形参分别占有不同的内存块,对形参的修改不会影响实参。
2.传址调用
通过指针传递方式,形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作。
五、函数的嵌套调用和链式访问
1.嵌套调用
函数和函数之间可以根据实际的需求进行组合的,也就是互相调用的。
示例:
#include<stdio.h>
int main()
{
printf("Hello world\n");
return 0;
}
我们先调用了main()函数,又在main()中调用了printf()函数,这就是嵌套调用。
2.链式访问
有时候我们会将一个函数的返回值,作为另一个函数的参数。
示例:
#include<string.h>
#include<stdio.h>
int main()
{
char arr[10] = "abcdef";
printf("%d", strlen(arr));
return 0;
}
上述代码中,strlen() 函数的返回值变成了printf()函数的参数,这就把这两个函数像链子一样串联起来,也就是链式访问。
六、函数的声明和定义
1.函数的声明
1. 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数 声明决定不了。2. 函数的声明一般出现在函数的使用之前。要满足 先声明后使用 。3. 函数的声明一般要放在头文件中的。
2.函数的定义
函数的定义是指函数的具体实现,交待函数的功能实现。
//定义函数
int add(int x,int y)//加法函数
{
return x + y;
}
int sub(int x, int y)//减法函数
{
return x - y;
}
七、函数递归
1.什么是递归
递归指的是在函数的定义中使用函数自身的方法。
示例:
void recursion()
{
statements;
... ... ...
recursion(); /* 函数调用自身 */
... ... ...
}
int main()
{
recursion();
}
2.递归的两个必要条件
1.存在限制条件,当满足这个限制条件的时候,递归便不再继续。2.每次递归调用之后越来越接近这个限制条件.
3.递归与迭代
什么是迭代?
迭代实际上就是重复,如果只讨论我们比较熟悉的程序设计操作,迭代在程序中就表示循环。
函数递归和迭代的优缺点
函数递归中我们一层一层调用函数,它的优点是所需代码量少,简洁。但缺点主要有两个,一方面,大量重复的计算拖慢了程序的运行速度;另一方面,函数每一次被调用的时候都需要在栈区开辟相应的空间,当递归过深时可能会出现栈溢出。(栈区的空间已经被用完了,程序无法继续进行了)
当我们使用迭代时,循环不需要大量调用函数,重复的计算会少很多,这个程序的运行速度会加快不少,只是这个程序的代码量会大很多。