引言
在C语言中我们⼀般会见到两类函数: 库函数和自定义函数
下面就分别介绍这两种函数
库函数
那么何为库函数呢?c语言的国际标准ANSI C规定了⼀些常⽤的函数的标准,被称为标准库,那不同的编译器厂商根据ANSI提供的C语言标准就给出了⼀系列函数的实现。这些函数就被称为库函数。
换句话来说就是我们所用的编译器自带的函数,例如我们平时使用的printf以及scanf都是库函数。但有一点我们要注意的是在使用这些库函数时我们要引相应的头文件例如:#include<stdio.h>。
库函数的使用方法及如何学习库函数
在这里我给大家推荐两款非常好用的工具
1.c/c++官方链接: link
2. cplusplus.com
在红色框的位置我们可以搜索我们想找的函数,蓝色框的位置可以看到一些常见的头文件,点进去可以看到其中包含的函数。
以sqrt()
函数为例,他给我们介绍了这个函数的参数及返回类型,也给我们举了例子,可以说是相当完善了。
自定义函数
函数的形参和实参
实际参数就是真实传递给函数的参数。
形式参数是不会向内存申请空间,不会真实存在的。形式参数只有在函数被调⽤的过程中为了存放实参传递过来的值,才向内存申请空间,这个过程就是形式的实例化。
那么两者有怎样的关系呢?我i们一个代码来看一下
int Add(int x, int y) { int z = 0; z = x + y; return z; } int main() { int a = 0, b = 0; scanf("%d%d", &a, &b); int ret = Add(a, b);//加法函数,ret接收返回值 printf("%d\n", ret); return 0; }
运行的结果如下。我们分别在监视窗口看看&a
,&b
,&x
和&y
的地址如何?
我们在调试的可以观察到,x和y确实得到了a和b的值,但是x和y的地址和a和b的地址是不⼀样的,所以我们可以理解为==形参是实参的⼀份临时拷贝。==还有就是对形参的修改是不会影响实参的。
数组做函数的参数
这里我们需要知道数组传参的几个重点知识:
• 函数的形式参数要和函数的实参个数匹配
• 函数的实参是数组,形参也是可以写成数组形式的
• 形参如果是⼀维数组,数组大小可以省略不写
• 形参如果是⼆维数组,行可以省略,但是列不能省略
• 数组传参,形参是不会创建新的数组的
• 形参操作的数组和实参的数组是同⼀个数组
我们比较这两段代码,很明显发现代码1计算的数组长度错了,那这是为什么呢?让我们仔细分析一下:
看图中我圈出来的地方发现,此时传递的arr
既和&arr[0]
相同,不难发现当数组作为函数的参数传参时,传递的是数组首元素的地址。
函数的嵌套调用和链式访问
嵌套调用
嵌套调用顾名思义就是函数间的互相调用,这里我们还是以一段代码作为例子吧:
int is_leap_year(int y) { if(((y%4==0)&&(y%100!=0))||(y%400==0)) return 1; else return 0; } int get_days_of_month(int y, int m) { int days[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int day = days[m]; if (is_leap_year(y) && m == 2) day += 1; return day; } int main() { int y = 0; int m = 0; scanf("%d %d", &y, &m); int d = get_days_of_month(y, m); printf("%d\n", d); return 0; }
我们在main()
函数中调用get_days_of_month()
函数在此函数中有嵌套调用了is_leap_year()
函数来判断是否为闰年,这就是函数的嵌套调用,在日后我们写一些大工程时就会经常用到函数的嵌套调用。
链式访问
所谓链式访问就是将⼀个函数的返回值作为另外⼀个函数的参数,像链条⼀样将函数串起来就是函数的链式访问。
直接上代码:
int main() { printf("%d\n",strlen("abcdef"));//链式访问 return 0; }
此处我们就直接将strlen()
函数的返回值作为函数参数给了printf()
。
函数的声明和定义
单个文件
我们只需要记住一点就是:先声明在使用
另外函数的定义也是⼀种特殊的声明,所以如果函数定义放在调⽤之前也是可以的。
多个文件
如果代码量较大时,不会将所有的代码都放在⼀个文件中,我们往往会根据程序的功能,将代码拆分放在多个文件中。
⼀般情况下,函数的声明、类型的声明放在头文件(.h)中,函数的实现是放在源文件(.c)文件中。
我们就以Add()
函数为例吧:
add.c
//函数的定义 int Add(int x,int y) { return x+y; }
add.h
//函数的声明 int Add(int x,int y);
test.c
int main() { int a=10, b=20; //函数调用 int ret=Add(a,b); printf("和为%d\n",ret); return0; }
运行结果:
多个文件的书写代码可以清晰的区别声明和定义,更好观察函数的实现,也大大的提高了代码的可读性。