目录
前言
中学的学习过程中,我们已经了解数学中函数的概念,但是你了解C语言中的函数吗?百度百科对计算机中的函数给出了这样的定义:
计算机的函数,是一个固定的一个程序段,或称其为一个子程序,它在可以实现固定运算功能的同时,还带有一个入口和一个出口,所谓的入口,就是函数所带的各个参数,我们可以通过这个入口,把函数的参数值代入子程序,供计算机处理;所谓出口,就是指函数的函数值,在计算机求得之后,由此口带回给调用它的程序。
一、函数的分类
1.库函数
我们在编写C语言代码的时候,有时候会频繁地进行一些相同的基本操作,为了方便程序员进行编程开发,库函数应运而生。
例如:对于我们最熟悉的printf函数和scanf函数,如果不引用头文件#include <stdio.h>就无法正常使用
要想代码更加简洁高效,我们需要学习积累一些常用的库函数的使用方法。在这里我向大家推荐两个网站:
cplusplus.comhttps://cplusplus.com/
cppreference.comhttps://zh.cppreference.com/当然,msdn这款软件也非常好用,在断网情况下也可以使用哦~
接下来列举一些C语言常用的库函数:
1.输入输出函数(<stdio.h>)
2.字符串操作函数(<string.h>)
3.内存操作函数(<stdlib.h>)
4.时间函数(<time.h>)
5.数学函数(<math.h>)
2.自定义函数
ret_type function_name(para1,para2...) { statement; } ret_type 返回类型 function_name 函数名 para1,para2... 函数参数(可以是一个或者多个,甚至可以没有参数) 示例代码: #include <stdio.h> int Add(int x, int y) { return x + y; } int main() { int a = 0; int b = 0; scanf("%d %d", &a, &b); int sum = Add(a, b); printf("%d", sum); return 0; }
二、函数的参数
1.实际参数(实参)
实际传给函数的参数,例如上文示例代码中的a和b就是实参
实参可以是常量、变量、表达式、函数等
在函数调用中,必须有实际确定的值
2.形式参数(形参)
函数名后面括号内由于接受实参的变量,例如上文示例代码中的x和y就是形参
形参只有在函数调用的过程中分配内存,调用结束后释放内存
我们可以看到,a的地址与x的地址并不相同,b的地址与y的地址也不相同,而且函数调用结束后x、y无法打印出来,我们可以这样理解:形参是实参的一份临时拷贝
三、函数的调用
我们先来看一道题目:
自定义一个函数,交换两个整型变量的值
请问swap1和swap2哪个函数能够完成题目的要求呢? void swap1(int x, int y) { int tmp = 0; tmp = x; x = y; y = tmp; } void swap2(int *x, int *y) { int tmp = 0; tmp = *x; *x = *y; *y = tmp; } int main() { int a = 2; int b = 3; swap1(a, b); printf("a=%d, b=%d\n", a, b); swap2(&a, &b); printf("a=%d, b=%d", a, b); return 0; }
在了解形参和实参之后,相信你已经对这样的结果并不惊讶了。函数调用有以下两种形式:
1.传值调用
函数的形参和实参分别占用不同的内存块,对形参的修改不会影响到实参,上文中的Add函数与swap1函数都是传值调用,但是传值调用也可以完成swap2进行的操作哦~,读者可以自己思考一下
2.传址调用
传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。这种传参方式可以让函数和函数外边的变量建立起真正的联系,如此一来,就能够在函数内部直接操作函数外部的变量
3.函数的嵌套调用
#include <stdio.h> int main() { printf("函数的嵌套调用\n"); return 0; } --我们在main函数里面调用了printf函数,这样一层层在函数内部调用函数的形式称为函数的嵌套调用
4.函数的链式访问
此处函数相当于把Add(a, b)与a分别作为两个参数,调用Add函数,这种像链条一样的函数调用方式称为函数的链式访问
四、函数的声明和定义
1.函数的声明
函数的的声明一般放在头文件(.h)中
函数一般需要先声明使用
函数声明主要是记录函数的类型、函数名、函数的参数及其类型、是否有返回值
test.h int Add(int x, int y) ********************** test.c int Add(int x, int y) { return x + y; }
2.函数的定义
函数定义主要实现函数的功能
函数不能嵌套定义,但是可以嵌套调用
3.代码的分块编写
代码分块编写具有诸多好处,总体来说利大于弊(尽管把所有的代码放在一个.c的文件夹里面确实便于自己的编写)
能够提高团队合作的效率
能够提高代码的安全性
五、函数递归与迭代
1.函数递归
如果我们把一个问题分解为很多步骤,其中每一步都要用到前一步或前几步的结果,这种计算过程就称为递归,函数递归就是用递归的形式一层层地调用函数
2.迭代
迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复被称为一次"迭代",而每一次迭代得到的结果会被用来作为下一次迭代的初始值。简而言之,类似于循环
为了能够更好地区分它们,我们接下来看一道经典的例题:
斐波那契数列:1 1 2 3 5 8 13 ...(每一项的值是前两项之和)
打印斐波那契数列的第20项
递归 #include<stdio.h> int fib(int n) { int rabbits = 0; if (n<=2) { rabbits = 1; } else { rabbits = fib(n - 1) + fib(n - 2); } return rabbits; } int main() { int day = 0; scanf("%d", &day);//day=20 printf("%d",fib(day)); return 0; }
迭代 #include<stdio.h> int main() { int f1 = 1; int f2 = 1; for (int i = 1; i <= 10; i++) { printf("%d %d ", f1, f2); f1 = f1 + f2; f2 = f1 + f2; } return 0; }
3.递归与迭代的比较
递归能够把大问题转化为小问题,可以有效减少代码量,但是递归太深容易造成栈溢出
迭代编写程序可能代码不如递归简洁,但是代码运行占用的时间和空间更少
递归和迭代大部分问题可以相互转换
总结
这里对文章进行总结:
以上就是今天要讲的内容,本文仅仅简单介绍了C语言中函数的一些基本知识,如果想要提高自己的能力,可以去尝试一些题目或者学习使用一些函数