1.函数的定义
函数实际上是就是一个子程序
函数的由来:为了方便我们在写大型程序(代码多)时,将其中具有特定功能的某部分代码单独抽出来进行封装,形成函数(代码块/子程序),程序也就模块化出来了(这部分做什么那部分做什么),使编程时逻辑思路变得清晰,同时相对于未抽出的代码,我想使用时就可调用(独立性),不需要重复写。
2.函数的分类
(1).库函数
库函数的由来:
库函数就是函数库里的函数,起初本来没有函数库,每个程序员都得自己写函数,这样一来就出现许许多多的函数,其中就会存在一些常用的函数(如:printf()),但这些相同功能的函数是由不同的程序员用不同的代码写出来的,代码不同导致别人看你的代码时却要多发时间,所以使用起来不便于程序员之间阅读和交流,就导致代码的可移植性差,而且这种反复造轮子会使得开发效率变低。
之后官方就出来说了:“你们都别重复写了,我来制定一个标准(参数,函数名,返回类型都限定),将常用的函数放到函数库里形成库函数,你们只需要引用头文件就可以去使用函数了。”
如:官方说:别重复写printf()了,我来写printf(),要使用printf()引用头文件stdio.h
(注意:库函数是代码最简单,效率最高的函数;库函数一般是C语言标准规定好,由编译器厂家提供实现。)
库函数的学习方法:
这里先给大家推荐几个搜索网站:
第一个建议点击右上角使用旧版本,第二和第三的区别,前面一个英文后面一个中文
下面是以第一个网站为例子,教大家如何使用
第一步:在Search(搜索)栏输入你想学习的库函数名
第二步:查看函数的作用,如下(重要)
第三步:就是函数参数(Parameters)进行详细解析,这里我们不需要仔细看,只需要知道怎么用就行。
第四步:查看函数的返回值,这里需要认真看一看
总的来说学习一个库函数,重点知道它的作用,懂得函数的参数,返回类型是什么就行了,不懂的时候就看一下Example下面的例子,参数的详细解析稍微看看就行了,一堆啰嗦的话没必要看,重要是会用!!!
(2).自定义函数
库函数只是一些我们会经常用到函数,不可能你想要一个什么功能的函数就能在库函数里面找到,所以就需要我们自己敲代码来创建函数,这就是自定义函数。
3.函数的创建
创建方式:
ret_type fun_name(para1, * )
{statement;
}
ret_type 函数的返回类型(return_type)
fun_name 函数名称(function)
para1,para2,* 函数的形式参数(parameter1,parameter2,......)
statement; 函数的语句
" { } "花括号包括的这一部分语句可以称为函数体(函数的主体)
例子:
/*加法函数*/
int Add(int a,int b) //int-函数的返回类型;Add-函数名字;a,b为函数的形式参数
{
return a + b; //函数总语句
} //花括号包着的被称为函数体
4.函数的使用
例子:
#include<stdio.h>
int Add(int a,int b) //函数的定义,创建函数
{
return a + b;
}
int main()
{
int a,b;
scanf("%d %d",&a,&b);
int c = Add(a,b); //需要函数的时候,直接函数名字+"()"(函数调用操作符),括号里面加上参数
printf("%d",c);
return 0;
}
使用函数很简单哈哈,函数名加括号,要传的值方括号里就行了,这里也要知道这个小括号是函数调用操作符,先读取函数的名字, 剩余的作为参数传给函数
5.形式参数和实际参数
(1).概念:
形式参数:函数调用时创建的参数,随着函数的结束参数的值也跟着销毁。
实际参数:调用函数时给函数传的那个值,不会随着函数的结束而销毁。
(2).关系:
形式参数是实际参数的一份临时拷贝,形式参数的销毁并不会影响到实际参数的值。
举例分析:
#include<stdio.h>
//第二步:调用函数时,就到函数定义这进来,此时函数在栈区开辟空间,分配内存空间
int Add(int a,int b) //第三步:会创建变量来接收实际参数
{ //创建变量int a;int b;再把实际参数a,b的数值给创建的a,b
return a + b; //他们只是值相同,地址不同
}
//当函数被调用完,为函数和形式参数开辟的空间就会被销毁,自然形式参数就不存在了
int main()
{
int a = 1;
int b = 1;
int c = Add(a,b); //第一步:调用函数,a,b为实际参数,传给函数
printf("%d",c);
return 0;
}
形参和实参的地址:
6.传值调用和传址调用
(1).传值调用:
传值调用就是将实参的数值拷贝给形参,调用的是拷贝后的数值,实参和形参分别在不同的内存块,不会因为其中一个被影响而影响另一个。
比如:形参的类型是常见的数值变量类型,int,char,double,float等等。
(2).传址调用:
传址调用就是将实参地址拷贝给形参,然后使用解引用操作符*使用地址找到实际参数的内存空间,对它的数值进行操作。
比如:形参的类型是指针类型,int*,char*等等。
7.函数的声明与定义
(1).函数的声明
形式:
ret_type fun_name(para1, * );
ret_type 函数的返回类型(return_type)
fun_name 函数名称(function)
para1,para2,* 函数的形式参数(parameter1,parameter2,......)
" ; " 表示声明语句的结束
注意:函数的声明,形参的类型必须写,形参的名字可写可不写
作用:
函数的声明只是告诉编译器有着函数的存在(交代函数的返回值类型,函数名,函数参数类型),是否真的存在还是取决于函数是否定义。
(2).函数的定义
形式:
见上面3.函数的创建
作用:
函数的定义大体就是对函数功能的实现,完成函数,就说明函数存在了
(3).函数的声明与定义的联系
- 函数的定义是一种特殊的声明。
- 函数的使用前必须要有函数的声明或者函数的定义,前面没有函数的定义,在使用时编译器就找不到函数的存在。
8.函数的递归
概念:
函数自己不断地调用自己,这就是递推出去,当达到递推结束的条件,函数就结束被自己调用,返回值就会回归到上次函数被调用的地方,一路返回,这就是回归,回归是值的回归,最后得到函数的结果。
例子:
这里比较难画图,就不举例详细解释了,下次出一篇文章再详细探究函数的递归。
条件:
- 不能无限递归下去,必须存在递归结束的条件。
- 每一次递归都要更一步接近递归结束的条件。
9.嵌套调用和链式访问
(1).嵌套调用
概念:
嵌套调用就是指在函数内部调用函数
例子:
//加法函数Add,减法函数Sub
int test(int a,int b)
{
Add();//调用加法函数
Sub();//调用减法函数
......;//调用其他函数
}//这种在函数的内部调用函数的操作就是嵌套调用,函数里面嵌函数
//错误示例
void test()
{
int add(int a,int b)
{
return a + b;
}//函数定义
}函数定义里面不能有函数的定义,存在嵌套调用不存在函数嵌套定义
存在嵌套调用不存在函数嵌套定义
(2).链式访问
概念:
链式访问是指在调用函数时,可以在将其他函数的返回值作为函数的参数进行访问。
例子:
目录
函数的知识就结束了,下章见!!!