C语言 _ 函数 (一篇文章,轻松掌握)
目录
1. 什么是函数
第一,函数就是 C 语言的模块,一块一块的,有较强的独立性,可以相互调用。
第二,函数就是一系列 C 语句的集合,能完成某个特定的功能。需要该功能的时候直接调用该函数即可,不用每次都堆叠代码。需要修改该功能时,也只需要修改和维护这一个函数即可。
1.1 为什么需要函数
第一,将语句集合成函数的好处是方便代码重用。所谓“重用”,是指有一些代码的功能是相同的,操作是一样的,只不过针对的数据不一样,这时就可以将这种功能写成一个函数模块,以后用到这个功能时只需要调用这个函数模块就可以了,不需要再重复地编写同样的代码。这样可以解决大量同类型的问题,避免重复性操作。
第二,将语句集合成函数方便代码的维护。哪个功能出问题了,或者需要修改某个功能,那就只需要修改某个功能的函数就可以了。
所以,函数有利于程序的模块化。这实际上就是面向过程的思想。面向过程语言最基本的单位不是语句,而是函数。
2. 函数的分类
2.1 库函数
C 语言提供了极为丰富的库函数(几百个),比如 printf() 、strcpy()······,我们可以直接使用这些库函数来实现一些功能,极为方便。
重要的一点:使用库函数,必须包含 #include 对应的头文件。比如使用strcpy()函数,就要在开头敲上它所对于的头文件#include<string>
若不知道库函数对应的头文件,我们可以在http://www.cplusplus.com/中查看。
![]()
2.2 自定义函数
C 语言不仅提供了丰富的库函数,还允许用户定义自己的函数。
用户可以将自己的算法编成一个个相对独立的函数模块,然后通过调用来使用这些函数。在实际的C编程中用得最多的就是自己定义的函数。
3. 函数的组成定义和声明
3.1函数的组成和定义
return_type name (para1,para2···) { statement //具体实现的语句项 } //return_type 返回类型 //name 函数名 //para 函数参数
我们来应用一下 :
这里我们自定义了Add()函数,返回类型为int型,函数参数为int num1和int num2,这个函数实现了两个数的相加。
#include<stdio.h> int Add(int num1, int num2) { int add = num1 + num2; return add; } int main() { int a = 1, b = 2; printf("%d", Add(a, b)); }
3.2函数的声明
1. 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数声明决定不了。2. 函数的声明一般出现在函数的使用之前。要满足先声明后使用。(若函数定义在主函数之后,则一定要在主函数之前声明一次。反之则不用)例如:#include<stdio.h> int Add(int , int) ; //函数定义在主函数之后,则一定要在主函数之前声明一次。 //函数声明时 num1,num2 可以省略!!!! int main() { int a = 1, b = 2; printf("%d", Add(a, b)); } int Add(int num1, int num2) { int add = num1 + num2; return add; }
3. 若以分文件的书写,则函数的声明一般要放在头文件中的。
4. 函数的参数
4.1 实际参数
实际参数(实参)就是真实传给函数的参数,例如我们刚刚在2.2.1中举的例子:
#include<stdio.h> int Add(int num1, int num2) { int add = num1 + num2; return add; } int main() { int a = 1, b = 2; printf("%d", Add(a, b)); }
传给Add函数的a和b就是实参。
4.2 形式参数
形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例(分配内存单元),所以叫形式参数。
形参实例化之后其实相当于实参的一份临时拷贝。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。
在上面的那一段代码中参数num1,num2都是形参。
5. 函数的调用:
函数调用形成栈帧,该函数所定义的所以局部变量哦都在该函数的栈帧内进行空间开辟,函数返回时自动释放该函数的栈帧结构(临时变量具有临时性)
5.1 传值调用
函数的形参和实参分别占有不同内存块,传值调用对形参的修改不会影响实参。
5.2 传址调用
传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操
作函数外部的变量。传址传参对形参的修改会影响到实参。
6. 函数的访问
6.1函数的嵌套访问
函数内可以调用另一个函数
例:
#include<stdio.h> void Print(int num) { printf("%d", num); } int Add(int num1, int num2) { int add = num1 + num2; PRINT(add); } int main() { Add(); return 0; }
我们修改了上面的Add()函数,Add()依然是起到两数相加的作用,但是其内部调用了Print()函数,这就是函数的嵌套使用。
6.2 函数的链式访问
函数的链式访问就是把一个函数的返回值作为另外一个函数的参数。例:
#include<stdio.h> int Add(int num1, int num2) { int add = num1 + num2; } void PRINT(int num) { printf("%d", num); return 0; } int main() { int a = 1,b = 2; PRINT(Add(a,b)); //这里就是函数的链式访问 }
7. 函数递归
7.1什么是递归
函数调用自身的编程技巧称为递归。递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接 调用自身的 一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求 解,递归策略 只需少量的程序就可描述出解题过程所需要的多次重复算,大大地减少了程序的代码量。递归的主要思考方式在于:把大事化小
7.2递归所遵循的条件
1.有限次的递归,要有限制条件,不能发生无限递归的情况。2.子问题可被同逻辑解决。
7.2.1利用递归求10的阶乘
#include<stdio.h>
int Revers(int num)
{
if (num <= 1)
{
return 1;
}
return(num * (Revers(num - 1)));
}
int main()
{
printf("%d", Revers(10));
}
7.2.2计算斐波那契数
int Fib(int n)
{
if (n == 0)
return 0;
else if (n < 3)
return 1;
return Fib(n-2) + Fib(n - 1);
}
函数调用是有成本的(时间+空间),递归比非递归的形式更为清晰,代码简单。但是呢,函数调用成本可能会高,导致效率低。所以要根据实际情况来选择递归或者非递归。