【C语言】函数详解

1.什么是函数

如果你已经看过了我做的第一篇有关C语言的博客,那么你多少已经了解到一点了。如果没有看到,那么我就在这里再讲一遍。

这里的函数可能跟大家印象里的函数不是一个东西,大家印象里的函数基本都是中学阶段的一些东西,比方说什么f(x) = 4x - 6,而编程里的函数是 函数返回值类型+名字+参数+实现函数功能的语句+函数的返回值(由返回值类型决定)。是由一堆字母组成的语句。

对于中学阶段的函数,就拿f(x) = 4x - 6来说这个函数也可以是由:函数返回值类型+名字+参数+实现函数功能的语句+函数的返回值来组成。这里的函数名字就是f ,函数的参数就是x ,实现函数功能的语句就是2x+3 。
当你对中学的这个函数传入一个参数的值时,假如我们传参使得x = 2,那么这时函数的返回值就是4*2 - 6 = 2,那么2就是返回值,对应的是一个int类型(整数类型)。

那么对于我们现在学的函数,就拿我们最为熟知的"hello world"来说,它的函数的返回值类型为int,函数名就是main,并且这个函数没有参数(函数可以有参,也可以无参),实现函数功能的语句就是printf(“hello world\n”); ,函数的返回值为0。
在这里插入图片描述

简单来讲,函数就是为了负责完成某项特定任务。

2. C语言中函数的分类

  1. 库函数
  2. 自定义函数

2.1 库函数

我们常见的printf,scanf这两个就是库函数,大家也知道,当我们刚学习C的时候,老师总让我们记住#include<stdio.h>这个东西,那么这个东西的作用就是引printf,scanf这两个函数的头文件stdio.h。
听起来好像高大上的,但其实不难理解。库函数就是我们可以直接用的函数,不需要自己再去费劲把函数写出来,非常的方便,但是我们在用库函数的时候就必须要引用对应的头文件,不然就没法用。

简单来说,C语言常用的库函数都有:
IO函数(输入输出,我们常见的printf,scanf,getcha,putchar等等)
字符串操作函数(strlen,strcmp,strcpy等等)
字符操作函数(getchar等等)
内存操作函数(malloc等等)
时间/日期函数(time等等)
数学函数(平方根等等)
其他库函数

看着好像很多,但是我们不需要将这些库函数全部记下来,只需要多动手用用就行了。

2.2 自定义函数

当然,库函数不能实现所有的我们所需要的功能,所以就得让我们自己去写函数,这样就是自定义函数。

像这样:
ret_type fun_name(para1, * )
{
statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1 函数参数

来个例子:求两个数的最大值
在这里插入图片描述

3. 函数的参数

3.1 实际参数(实参):

真实传给函数的参数,叫实参。
实参可以是:常量、变量、表达式、函数等。
无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。
就比如说上面的例子中,num1和num2就是实参。

3.2 形式参数(形参):

形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。

再来个例子:两数字相交换的函数。
在这里插入图片描述
我们可以看到这里我们想要让num1和num2交换,但是却没有实现,这是因为当我们传的参数不是地址的时候,swap1函数就只会将参数拷贝一份过去,并不会将这两个数真正的传过去,若想真正的传过去就需要用到指针。
像这样
在这里插入图片描述
这里涉及到了值传递和址传递,swap1就是值传递,swap2就是地址传递,址传递就是简单的进行拷贝,不会对原来的数据进行修改,但是地址传递就穿过去的时原来的数据,而不是又拷贝了一份过去。

这里值传递的时候二者的地址,可以看到是不相同的。
在这里插入图片描述
这里址传递可以看到,二者的地址是相同的。
在这里插入图片描述

在这里可以类比以下我们的现实生活,重名的人有很多,但是一个人只会住一个地方,地址就是这个人的住所。

通过地址寻找到的数据才是真正的数据,名字相同可不是真正的相同。

4.函数的嵌套调用和链式访问

4.1 嵌套调用

意思就是你写了两个函数,其中的一个函数在写的时候使用到了另一个函数,这就是函数的嵌套调用。

举例子:
在这里插入图片描述

这里要记住一句话:函数可以嵌套调用,但是不能嵌套定义。
意思就是你不可以在定义一个函数的时候再在这个函数内部又定义了一个新函数。
注意:上面的例子是在函数内部调用另一个函数,而不是定义另一个函数。

4.2 链式访问

意思就是:把一个函数的返回值作为另外一个函数的参数。

例子:在这里插入图片描述
在这里strlen的参数并不是直接给了一个字符串,而是一个strcat函数,将这个函数的返回值作为了strlen的参数。

再来一个:
在这里插入图片描述
结果是4321,这是因为printf函数的返回值是打印在屏幕上字符的个数,也就是说,这条语句在执行的时候就是先执行最内部的函数printf(“%d”, 43),然后再执行中间的printf,最后执行最外层的。那么最内层在屏幕上打印的是43,占用了两个位置,那么返回值就是2,所以中间的打印的就是2,中间printf的返回值就是1,然后最外层打印的就是1啦。

5.函数的声明和定义

5.1 函数声明:

  1. 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数
    声明决定不了。
  2. 函数的声明一般出现在函数的使用之前。要满足先声明后使用。
  3. 函数的声明一般要放在头文件中的。

5.2 函数定义:

函数的定义是指函数的具体实现,交待函数的功能实现。

比如说,在调用一个函数的时候,这个被调用的函数的定义在所调用的函数的位置之下,那么这时候就需要给这个被调用函数在所调用函数的位置之上先声明一下
例如:
在这里插入图片描述

但是,上面的例子只是我们在学校能够学到的,在我们以后真正工作的收就不是这样了,我们需要自己去搞.h文件(放声明)和.c文件(放定义)。
如下:
在这里插入图片描述

6. 函数递归

6.1 什么是递归?

程序调用自身的编程技巧称为递归.
递归做为一种算法在程序设计语言中广泛应用。
一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
递归的主要思考方式在于:把大事化小

6.2 递归的两个必要条件

存在限制条件,当满足这个限制条件的时候,递归便不再继续。
每次递归调用之后越来越接近这个限制条件。

先来一个简单点的例子:
在这里插入图片描述

那么这里就要仔细拆开讲一讲了。
在这里插入图片描述
这里跟着箭头走就是详细过程了,这要是打字讲的话是很难讲的,可惜你们不在我跟前,要是在我跟前我就能给你讲得明明白白的。

下面再来一个例子:斐波那契数列(前两个书都为1,后面的数等于前两个数之和:1,1,2,3,5,8…)
数学好的同学应该高中都知道这个数列了,那么怎么实现呢,可以用递归。
在这里插入图片描述
当然,一般能递归的也就可以迭代,而且迭代的效率会更高一点,但同时代码量也会多一点,如下:
在这里插入图片描述
打击仔细琢磨琢磨,多练练就好。

结束。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

先搞面包再谈爱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值