• C语言函数章--第二弹(让冤种室友用你的函数,但不给他看函数源码)


    前言
    💖作者龟龟不断向前
    简介宁愿做一只不停跑的慢乌龟,也不想当一只三分钟热度的兔子。
    👻专栏C++初阶知识点

    👻工具分享

    1. 刷题: 牛客网 leetcode
    2. 笔记软件:有道云笔记
    3. 画图软件:Xmind(思维导图) diagrams(流程图)

    在这里插入图片描述

    如果觉得文章对你有帮助的话,还请点赞,关注,收藏支持博主🙊,如有不足还请指点,博主及时改正

    函数–第二弹

    🚀1.函数的返回值

     

    🍉如何设计返回值

      既然有些函数不需要返回值,有些函数需要返回值,那我们该如何确定呢?答案很简单:根据需求来

    • 如果一个函数的需求是:只需要打印某些图案,那么他是不需要返回值(void)的。

      例如我们上篇文章猜数字小游戏里面的菜单函数menu

    • 如何一个函数的需求是:只需要改变外部变量的值,那么它也可以设计成void通过传址调用即可

      例如我们上篇文章所说的交换函数Swap

      void Swap(int* x, int* y)
      {
      	int tmp = *x;
      	*x = *y;
      	*y = tmp;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 如果一个函数的需求是:求出某个值,那么它可以设计成需要返回值的,将求出的那个值通过return来返回给调用它的程序。

      例如我们熟悉的 最大值函数Max 加法函数Add

     

    🍉那些模棱两可的函数写法
    1. 返回类型不写

        当函数的返回类型未指明时,编译器默认返回类型为int类型,并且会根据编译器自己的方式来确定返回值

      #include
      
      test()
      {
      	printf("hello world\n");
      }
      
      int main()
      {
      	int ret = test();
      	printf("%d\n", ret);//这次的返回值是test打印在屏幕中的字符个数,算\n
      	return 0;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13

      在这里插入图片描述

       

    2. 无函数参数时,不写void

        当函数参数时,不写void时,我在在调用该函数时是可以传参的(C语言设计不严谨的地方),只是函数不接受而已

      #include
      
      void test()
      {
      	printf("hello world\n");
      }
      
      int main()
      {
      	int ret = test(100);//编译通过
      	printf("%d\n", ret);//这次的返回值是test打印在屏幕中的字符个数,算\n
      	return 0;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13

       

        不过这种写法影响不大,大部分同学还是会采用这种写法

       

       

    🚀2.嵌套调用 and 链式访问

     

    🍉嵌套调用

      函数和函数之间可以根据实际的需求进行组合的,也就是可以互相调用的。

    #include
    
    void Star()
    {
    	printf("*");
    }
    
    void three_stars()
    {
    	for (int i = 0; i < 3; ++i)
    	{
    		Star();
    	}
    	printf("\n");
    }
    
    int main()
    {
    	three_stars();
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

     

    图解

    在这里插入图片描述

      虽然这个代码没有展现出嵌套调用的价值,但是在一些大型工程中,嵌套调用是必要的,实现高内聚,低耦合的要求

    也使得程序更容易被维护。

     

    🍉链式访问

    概念:

    把一个函数的返回值作为另外一个函数的参数

    在这里插入图片描述

     

    🍇求三个数的最大值

     

    求两个数的最大值

    相信大家现在可以10秒之内就能将这个函数实现了

    int Max(int x, int y)
    {
    	return x > y ? x : y;
    }
    
    • 1
    • 2
    • 3
    • 4

     

    求三个数的最大值

    这里大家可能会想到if条件判断来实现一个求三个数最大值的函数,但如果再限制一下,只让你使用Max(两个数的最大值),你能否求出三个数的最大值呢?

    没错,我们只需要先求出前两个数的最大值,再将这个最大值跟第三个数比较即可,如下:

    #include
    
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

     

    🍇经典例题:来自printf的链式访问

    那么我们首先要弄清楚printf的返回值是什么,上篇文章我们已经介绍了如何学习库函数–查文档

    找到函数的返回值的介绍部分

    在这里插入图片描述

     

    现学现用:大家可以思考一下,下面的程序ret的值是多少

    #include
    
    int main()
    {
        int ret = printf("hello world\n");
        printf("ret = %d\n",ret);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    答案是:12,因为这个printf输出了hello world\n这些字符,\n转义字符,算一个字符,一共有12个

     

     

    经典例题

    #include
    
    int main()
    {
    	printf("%d", printf("%d", printf("%d", 43)));
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    答案: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
    
    int main()
    {
    	printf("%d\n", Max(100, 200));
    	return 0;
    }
    
    int Max(int x, int y)
    {
    	return x > y ? x : y;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

     

    在这里插入图片描述

     


    在这里插入图片描述

     

     

      所以有些课本经常是这样写的

    #include
    
    //声明部分
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    即上述的int Max(int x, int y);–会告诉编译器后面有Max函数

    具体有没有就要看你是否真的定义了

     


     

    🍉工程化写法(分模块)

    通常我们将函数的声明放在.h即头文件当中

    将函数的定义放在.c文件当中

    当test.c里面要使用该函数时,只需要包含对应的头文件即可

    这样就很好地达到了分工明确,模块编程,也便于代码维护和查找错误

    库函数的头文件的包含方式为#include<头文件>

    库函数的头文件的包含方式为#include“头文件”

     

     

    🚀4.浅浅地使用一下静态库(lib文件)

    🍉不显示源码给公司使用项目

     

    场景:你是一个CSDN的大牛博主,每天写着优良的代码,并且在CSDN平台分享,而且在gitee上面有着自己的仓库

    仓库里面有着开源项目,私有项目。突然有一天有个公司找上了优秀的你,想让你实现某个项目租给公司使用。

    那么当你实现完了这个项目,想要给公司使用,但是又不想让公司看到你的源码,该怎么办呢?

     

    1. 实现自己的项目(项目名Add)–已经测试功能完整

      里面有头文件Add.h(放着Add的头文件包含)

      里面有源文件Add.c(放着Add功能实现的源码)

    2. 修改项目属性,生成lib文件

      在这里插入图片描述

       

      在这里插入图片描述

       

        F7编译,生成.lib文件

      在这里插入图片描述

       

        我们按照上述的路径,找到.lib即可

      在这里插入图片描述

        大家可以使用记事本打开Add.lib是乱码,看不懂的

       

    3. 将Add项目的头文件Add.lib文件放到公司项目当前目录下

    我们将头文件和Add.lib租给公司,然后它只需要将这两个文件放到当前目录下即可

    在这里插入图片描述

    在这里插入图片描述

     

    1. 包含头文件,导入静态库

    在这里插入图片描述

     

    在这里插入图片描述

     

    总结

    1. 将自己的项目生成lib文件
    2. 然后将该自己项目的头文件和lib文件,放到另一个项目的工作目录中
    3. 在另一个项目中包含头文件,导入静态库

     

    大家可以试一试,不需要仔细地了解静态库和动态库的知识,也是可以玩一下的。很有意思!

     

    本篇文章就讲到这里,下期讲解函数的强化训练–函数递归,咱们下期见

     

    点赞

  • 相关阅读:
    普林斯顿算法讲义(四)
    使用GoFrame+Vue+ElementUI框架搭建的管理系统
    【快速上手ESP32(基于ESP-IDF&VSCode)】07-I2C(附BH1750实战代码)
    vue v-model与.sync详解
    Docker(第四部分)
    【C++】深拷贝和浅拷贝 ③ ( 浅拷贝内存分析 )
    【剑指Offer】16.数值的整数次方
    牛客SQL必会知识
    PyQt5 & PyQt6 Designer 的安装
    C++ 重载运算符和重载函数
  • 原文地址:https://blog.csdn.net/m0_64361907/article/details/127645280