? ? ? ? 这里我们讲的不是数学里的函数,而是C语言中的函数,在C语言中,函数是一个完成某项特定任务的一小段代码,实际就是子程序,我们将子程序习惯叫作函数。那函数的存在意义是什么呢?先来看看下面一段代码。
#include<stdio.h>
int Add(int x, int y)
{
return x + y;
}
int main()
{
int a, b;
scanf("%d%d", &a, &b);
int ret = Add(a, b);
printf("%d", ret);
return 0;
}
? ? ? ?我们可以将完成特定的功能的代码写在函数里,大家可能会想,就一个加法函数会不会大题小作了,但是大家要把眼光看得长远一点,如果是几千行代码的小工程呢?你把它全部写在main函数里,不仅不美观,更加重要的是难以进行后期的优化和修改,所以写函数的好处就是可以将工程里的功能分解成一个个函数去实现,最后程序可以通过main函数进行函数调用,完成任务。
? ? ? ?我们在创建函数的时候还应该遵循高内聚低耦合的准则,就是一个函数只负责特定的功能,最好就是只负责一个功能的实现,这样也有助于后期我们去优化代码和修复bug,这里大家可以参考一下我的扫雷代码中我对函数的处理https://blog.csdn.net/liwuqianhzc/article/details/134994784
? ? ? ?库函数是由不同的编译器厂商按照ANSI(C语言的国际标准)编写的,它们的实现方式可能不同,当时标准是相同的,大家可以自行在官方网站上查阅和学习库函数的使用方法。
? ? ? ?这里提供一个查阅库函数的官方网站https://legacy.cplusplus.com/reference/clibrary/
? ? ? ?那我们来一起学习如何阅读文档吧。这里以strlen为例子:
首先就是为函数的概括,这个概括能这可以让我们知道这个函数的返回类型和需要传递的参数。
返回类型为size_t ,接收的参数为const char* str
最重要的就是头文件了,它在函数页面的旁边:就是下图红笔圈出来的,其中string.h就是函数的头文件
函数功能和函数自身的介绍:
代码举例:
相关函数链接:
? ? ? ?在实际工程中,库函数并不能覆盖到所有的地方,因此就需要程序员自行定义函数去实现相应的功能。这种函数就叫作自定义函数。
ret_type fun_name(形式参数)
{
语句;
}
? ? ? ?首先ret_type 是函数的返回类型,如int、double、void等等,fun_name是函数的名字(这里建议取一个有意义的函数名字,方便阅读代码),(形式参数)就是这个函数需要传递的参数是什么。最后就是完成函数语句的书写,实现函数功能。
? ? ? ?通俗来说,实参就是传递给函数的参数,形参就是函数自行拷贝传递的实参的数值。也就是说形参和实参占用的是不同的内存空间。如果形参发生了改变是不会影响实参的。
实参的全名叫作实际参数,形参的全名叫作形式参数,我们习惯叫实参和形参。
先看一下代码:
#include<stdio.h>
int Add(int x, int y)
{
int sum = x + y;
x = 1;
y = 1;
return sum;
}
int main()
{
int a, b;
scanf("%d%d", &a, &b);
int ret = Add(a, b);
printf("%d\n", ret);
printf("%d\n", a);
printf("%d\n", b);
return 0;
}
这里我以这个代码为例,首先在main函数里我们输入了两个数值分别是a,b;这就是实参。
我们将a,b传递给Add函数,在Add函数里,x,y就是形参。
一起看看运行结果图:
这里就可以看出尽管形参x,y都发生了改变,是不会影响实参a,b的改变的,因为形参和实参的地址是不一样的,就像两个双胞胎尽管长得一样,但是他们的性格是不太一样的,你改变了一个双胞胎的性格,是不会影响到另一个双胞胎的。
眼见为实,我们来看一下形参和实参的地址吧。
显然形参和实参的地址是独立的,所以你改变了形参的值是不会影响实参的值的。这两个地址都不一样,你抄形参的家,关我实参什么事。
? ? ? ?在自定义函数中,我们常常需要写return,一般来说,有返回类型(除了void)都要写上return语句;而没有返回类型的(就是void)我们一般不写return ,如果你想写,就写上return;就可以了。
? ? ? ?使用注意事项:return返回的值和函数返回类型不同时,系统会自动将返回值隐式转换为函数的返回类型,也就是函数的返回值一定是函数的返回类型,这里提醒,你写的函数返回类型和返回值一定要保持一致,否则可能会达不到你的预期值。
? ? ? ?嵌套调用就是函数与函数之间相互调用,这个很好理解,就像上面的代码一样main函数调用了Add函数。
#include<stdio.h>
void print2()
{
printf("Welcome\n");
}
void print1()
{
printf("hello\n");
print2();
}
int main()
{
print1();
return 0;
}
这里main函数调用print1函数,print1调用print2函数.
? ? ? ?链式访问就是将一个函数的返回值作为另外一个函数的参数,像一条链条一样将函数串连起来。
Add函数的返回值作为printf的参数,于是便打印出30.
? ? ? ?自定义的函数在调用的时候需要两个步骤,声明和定义,就是说如果自定义函数在main函数前面的时候,就无需声明,直接调用即可,这里函数的定义同样也是一种特殊的声明。
#include<stdio.h>
int Add(int x, int y)
{
return x + y;
}
int main()
{
int a, b;
scanf("%d%d", &a, &b);
int ret = Add(a, b);
printf("%d", ret);
return 0;
}
如果自定义函数在mian函数后面,调用的时候就要先进行函数声明。
#include<stdio.h>
int Add(int x, int y);
int main()
{
printf("sim=%d\n", Add(10, 20));
return 0;
}
int Add(int x, int y)
{
return x + y;
}
? ? ? ?库函数的使用一定要包含自身对应的头文件例如你想使用sqrt函数,就一定要包含math.h的头文件。
#include<stdio.h>
#include<math.h>
int main()
{
double ret = sqrt(4.0);
printf("%.0lf", ret);
return 0;
}
? ? ? ?完成工程一般有两种形式,一种时单文件形式,一种时多文件形式,这里大家可以参考我的扫雷代码,里面有单文件形式和多文件形式。https://blog.csdn.net/liwuqianhzc/article/details/134994784
? ? ? ?尽管有两种形式,但是我们会更加倾向于多文件形式,因为一个大型项目时由多人合作完成的,总不能只有一份文件,你正在写着,别人就不用写了,因此我们需要多文件来处理一个大型的项目,不仅如此,多文件还能让我们阅读更加方便,修改优化等等也会更方便。
? ? ? ?多文件书写需要由专门的头文件(用于存放宏,函数声明,所需要的库函数的头文件),还有负责函数功能实现的代码文件,以及存放程序主逻辑和运行入口(main函数)的文件。详细内容可见https://blog.csdn.net/liwuqianhzc/article/details/134994784
那么我们只要在除了game.h这个头文件,其他文件上写上incude"game.h"就可以了。
? ? ? ?感谢你阅读到最后,希望这篇文章能帮助到你。制作不易,如果可以,能点个赞支持一下吗?我将会在本专栏上持续推出作品~~ 点个关注,下次不迷路哦!