前言
💖作者:龟龟不断向前
✨简介:宁愿做一只不停跑的慢乌龟,也不想当一只三分钟热度的兔子。
👻专栏:C++初阶知识点👻工具分享:
- 刷题: 牛客网 leetcode
- 笔记软件:有道云笔记
- 画图软件:Xmind(思维导图) diagrams(流程图)
如果觉得文章对你有帮助的话,还请点赞,关注,收藏支持博主🙊,如有不足还请指点,博主及时改正
函数–第二弹
文章目录
- 函数--第二弹
- 🚀1.函数的返回值
- 🍉如何设计返回值
- 🍉那些模棱两可的函数写法
- 🚀2.嵌套调用 and 链式访问
- 🍉嵌套调用
- 🍉链式访问
- 🍇求三个数的最大值
- 🍇经典例题:来自`printf`的链式访问
- 🚀3.函数的声明和定义
- 🍉工程化写法(分模块)
- 🚀4.浅浅地使用一下静态库(lib文件)
- 🍉不显示源码给公司使用项目
🚀1.函数的返回值
🍉如何设计返回值
既然有些函数不需要返回值,有些函数需要返回值,那我们该如何确定呢?答案很简单:根据需求来。
如果一个函数的需求是:只需要打印某些图案,那么他是不需要返回值(
void
)的。例如我们上篇文章猜数字小游戏里面的菜单函数
menu
如何一个函数的需求是:只需要改变外部变量的值,那么它也可以设计成
void
,通过传址调用即可例如我们上篇文章所说的交换函数
Swap
void Swap(int* x, int* y) { int tmp = *x; *x = *y; *y = tmp; }
如果一个函数的需求是:求出某个值,那么它可以设计成需要返回值的,将求出的那个值通过
return
来返回给调用它的程序。例如我们熟悉的 最大值函数
Max
加法函数Add
🍉那些模棱两可的函数写法
-
返回类型不写
当函数的返回类型未指明时,编译器默认返回类型为
int
类型,并且会根据编译器自己的方式来确定返回值#include<stdio.h> test() { printf("hello world\n"); } int main() { int ret = test(); printf("%d\n", ret);//这次的返回值是test打印在屏幕中的字符个数,算\n return 0; }
-
无函数参数时,不写void
当函数参数时,不写void时,我在在调用该函数时是可以传参的(C语言设计不严谨的地方),只是函数不接受而已
#include<stdio.h> void test() { printf("hello world\n"); } int main() { int ret = test(100);//编译通过 printf("%d\n", ret);//这次的返回值是test打印在屏幕中的字符个数,算\n return 0; }
不过这种写法影响不大,大部分同学还是会采用这种写法
🚀2.嵌套调用 and 链式访问
🍉嵌套调用
函数和函数之间可以根据实际的需求进行组合的,也就是可以互相调用的。
#include<stdio.h>
void Star()
{
printf("*");
}
void three_stars()
{
for (int i = 0; i < 3; ++i)
{
Star();
}
printf("\n");
}
int main()
{
three_stars();
return 0;
}
图解:
虽然这个代码没有展现出嵌套调用的价值,但是在一些大型工程中,嵌套调用是必要的,实现高内聚,低耦合的要求
也使得程序更容易被维护。
🍉链式访问
概念:
把一个函数的返回值作为另外一个函数的参数。
🍇求三个数的最大值
求两个数的最大值
相信大家现在可以10秒之内就能将这个函数实现了
int Max(int x, int y)
{
return x > y ? x : y;
}
求三个数的最大值
这里大家可能会想到if条件判断来实现一个求三个数最大值的函数,但如果再限制一下,只让你使用Max(两个数的最大值),你能否求出三个数的最大值呢?
没错,我们只需要先求出前两个数的最大值,再将这个最大值跟第三个数比较即可,如下:
#include<stdio.h>
int Max(int x, int y)
{
return x > y ? x : y;
}
int main()
{
int a = 12;
int b = 20;
int c = 30;
int max = Max(Max(a, b),c);
printf("%d\n", max);
return 0;
}
🍇经典例题:来自printf
的链式访问
那么我们首先要弄清楚
printf
的返回值是什么,上篇文章我们已经介绍了如何学习库函数–查文档找到函数的返回值的介绍部分
现学现用:大家可以思考一下,下面的程序ret
的值是多少
#include<stdio.h>
int main()
{
int ret = printf("hello world\n");
printf("ret = %d\n",ret);
return 0;
}
答案是:12,因为这个printf
输出了hello world\n
这些字符,\n转义字符,算一个字符,一共有12个
经典例题:
#include<stdio.h>
int main()
{
printf("%d", printf("%d", printf("%d", 43)));
return 0;
}
答案:4321
解释
首先执行1号
printf
,输出43,43为两个字符,所以1号printf
返回值为2接着执行2号
printf
,接收了1号printf
的返回值2,输出2,2为1个字符,所以2号printf
的返回值为1最后执行3号
printf
,接收了2号printf
的返回值1,输出1
🚀3.函数的声明和定义
这个知识点也是小伙伴们在学习函数之初,最容易产生疑惑的地方:
为什么定义的函数老放在调用其的函数的上部,放在下面不行吗?
这里咱们要介绍下:编译器扫描代码是自上向下扫描的,如果遇到一下代码编译器会干什么
#include<stdio.h>
int main()
{
printf("%d\n", Max(100, 200));
return 0;
}
int Max(int x, int y)
{
return x > y ? x : y;
}
所以有些课本经常是这样写的
#include<stdio.h>
//声明部分
int Max(int x, int y);//提前跟编译器说,后面有个Max函数,你到时候遇到了就别大惊小怪了
int main()
{
printf("%d\n", Max(100, 200));
return 0;
}
//定义部分
int Max(int x, int y)
{
return x > y ? x : y;
}
即上述的
int Max(int x, int y);
–会告诉编译器后面有Max函数具体有没有就要看你是否真的定义了
🍉工程化写法(分模块)
通常我们将函数的声明放在.h即头文件当中
将函数的定义放在.c文件当中
当test.c里面要使用该函数时,只需要包含对应的头文件即可
这样就很好地达到了分工明确,模块编程,也便于代码维护和查找错误
库函数的头文件的包含方式为
#include<头文件>
库函数的头文件的包含方式为
#include“头文件”
🚀4.浅浅地使用一下静态库(lib文件)
🍉不显示源码给公司使用项目
场景:你是一个CSDN的大牛博主,每天写着优良的代码,并且在CSDN平台分享,而且在gitee上面有着自己的仓库
仓库里面有着开源项目,私有项目。突然有一天有个公司找上了优秀的你,想让你实现某个项目租给公司使用。
那么当你实现完了这个项目,想要给公司使用,但是又不想让公司看到你的源码,该怎么办呢?
-
实现自己的项目(项目名Add)–已经测试功能完整
里面有头文件Add.h(放着Add的头文件包含)
里面有源文件Add.c(放着Add功能实现的源码)
-
修改项目属性,生成lib文件
F7编译,生成.lib文件
我们按照上述的路径,找到.lib即可
大家可以使用记事本打开Add.lib是乱码,看不懂的
-
将Add项目的头文件和Add.lib文件放到公司项目当前目录下
我们将头文件和Add.lib租给公司,然后它只需要将这两个文件放到当前目录下即可
- 包含头文件,导入静态库
总结
- 将自己的项目生成lib文件
- 然后将该自己项目的头文件和lib文件,放到另一个项目的工作目录中
- 在另一个项目中包含头文件,导入静态库
大家可以试一试,不需要仔细地了解静态库和动态库的知识,也是可以玩一下的。很有意思!
本篇文章就讲到这里,下期讲解函数的强化训练–函数递归,咱们下期见