目录
往期精彩回顾,c语言笔记正在更新中!,敬请期待!
前言:
8-1函数的概念
8-2函数的定义
8-3函数的调用
8-4函数的值传递
8-5函数的声明
往期精彩回顾,c语言笔记正在更新中!,敬请期待!
所有往期c语言笔记均在c语言笔记专栏内
专栏链接:
c语言笔记_1zero10的博客-CSDN博客
前言:
本套笔记是基于英雄哪里出来c语言入门到精通课程整理的笔记
包含代码,代码演示结果,以及便于理解的插图
对于想要c语言入门,嵌入式c语言的入门的朋友来说,这是一套不可多得的教程
此教程分几篇文章发布,初步计划更新到函数(已更完),未来时间允许会继续更新
8-1函数的概念
函数就是一些经常需要用到的代码,给它封装起来,这样可以减少一些冗余代码,或者说减少重复的代码
一个大的程序是有很多很多程序块组成的,每一个模块实现一个特定的功能
函数英文:function 功能的意思
我们之前已经学过了很多函数
我们之前已经学过了很多的函数
比如说
main 函数程序的主函数,一个程序只能有一个
int main(){}
printf函数
printf("%d\n",);//格式化输出函数
scanf("%d",&x);//格式化输入函数
abs();//绝对值函数 比如 int y=abs(x);那么当你输入一个数,它会把这个数变成这个数的绝对值
//absolute
函数分为自定义函数和系统函数
系统函数就是printf scanf main abs这种函数,内部是怎么构成的,不用管,你只要明白怎么使用它即可
自定义函数,需要你自己去完善里面的内容,实现某一功能
以下介绍的主要是自定义函数
8-2函数的定义
我们之前学过的main函数其实就已经包含了函数定义的几个要素
我们一个一个来分析其中的要点:
1、返回值类型:可以是任意类型,整型,浮点型,字符型...
2、函数名:满足标识符的命名规则
#include <stdio.h>
int main(){
//标识符:人为定义的变量名等
//1.由字母,数字,下划线组成int a1_ = 1;printf("%d\n",a1_);
//2.不能以数字开头//int 1a = 2;
//3.大小写敏感int b = 2;int B = 2;printf("%d\n",b);printf("%d\n",B);
//4.不能为关键字//int for = 3; //不合法
//5.尽量一看就能看懂是什么意思int appcount = 4;printf("苹果的数量是:%d\n",appcount);return 0;
}
3、参数列表:就是这个函数需要哪些参数,需要传进去的,参数与参数之间用逗号隔开 //输出
4、函数体:就是实现函数功能的代码,可以是顺序结构,可以是分支结构,也可以是循环结构 //算法
5、return 返回值:范围值可以是整型,浮点型,字符型,甚至表达式。如果没有返回值就不用写return 返回值; //输出
比如说void函数就没有返回值
下面以自定义一个加法函数来举例:
那应该如何调用呢?下一节进行讲解
8-3函数的调用
函数调用分为两个部分:
第一个部分是输入,也就是调用方传入参数
第二个部分是输出,也就是函数给你的数据,也就是函数传递出来的返回值
对于函数内部如何实现,调用方不需要关心
下面我们把上一节的加法函数尝试调用一下
函数也是一种跳转结构
add(5,6);调用函数之后,直接跳转到上面函数定义的地方,开始执行函数体的内容,执行到return c=11时,跳转出来把返回值c=11赋值给x
函数的意义就在于调用方不用管函数内部是怎么实现的,只需要知道,比如说:诶!我现在需要一个从1一直加到n的函数,直接拿过来用就好了
下面我们来讲一下从1到n的累加的函数怎么定义的
我们之前已经学过了用循环来累加,下面我们用for循环来举例
但是 我们知道从1累加到n可以用等差数列来算
(1+n)xn/2
下面我们修改一下代码:
或者直接这样:
在算法里第一种for循环,是O(n),要遍历n次,第二种无论是图一还是图二,都是O(1),即无论n是多少都只算一次
显然第一种的运行效率与n有关,n越大,运行越久,效率越低。第二种运行效率与n无关
第二种方法速度更快
函数的好处就是当你需要重构代码,你觉得你的函数写的太烂了,只用修改函数,不需要修改下面的函数的调用,大大的方便
8-4函数的值传递
我们拿变量的交换来举例:
下面我们画个图来演示一下
1、申请了a,b两个变量,值为6和9开辟了两个内存空间存放6和9这两个数
a的在内存中的情况 在内存地址查询栏输入&a,下方b同理
开辟了四个字节的内存空间 前面四个00 00 00 00
b在内存中的情况
开辟了四个字节的内存空间 前面四个00 00 00 00
a在内存中的情况:第一个00变成了06,说明在0x0000009B754FFA34地址的内存中存进去了一个6
b在内存中的情况:第一个00变成了09,说明在0x0000009B754FFA54地址的内存中存进去了一个9
2、把a,b两个刚刚定义的参数传入swap函数,并且跳到上面swap定义的地方
3、swap函数又申请了两个变量一个是a,一个是b,都没用初始化,默认值是0
然后刚刚传进去的之前定义的a的值6给了刚刚定义的另一个a
刚刚传进去的之前定义的b的值给了刚刚定义的另一个b
这个a和b和之前的a和b不在一个内存空间
此时这个a和b在内存中的情况是怎么样的?
a:
b:
你看a和b的地址变了,说明跳转到swap函数后,函数小括号内的参数列表新定义了一个a和b
所以函数的值传递无法改变主函数里定义的并且传递到swap函数中的值
如果要实现真正的交换需要利用后面学的指针,代码如下:
#include <stdio.h>void swap(int *a, int *b) {printf("%d %d\n", *a, *b);int tmp = *a;*a = *b;*b = tmp;printf("%d %d\n", *a, *b);
}int main() {int a = 6, b = 9;swap(&a, &b);printf("%d %d\n", a, b);return 0;
}
8-5函数的声明
首先先定义并且调用一个加法函数举个例子:
那如果我们把函数的定义写在下面会怎么样?
warning了,原因是上面的代码是顺序结构的,从上往下执行,调用add函数时,函数定义的代码还没有执行到,所以编译器warning add未定义
那么我就要写在下面怎么办?前面需要加上函数的声明
现在就可以了
那么函数的声明是为了方便别人接手这个代码的时候能够快速明白代码结构和相关的功能模块