嵌入式开发学习(第二阶段 C语言基础)

函数

函数的概念

  • **函数:**实现一定功能的,独立的代码模块,对于函数的使用,一定是先定义,后使用。
  • 使用函数的优势:

​ ①我们可以通过函数提供功能给别人使用。当然我们可以也使用别人提供的函数,减少代码量。

​ ②借助函数可以减少重复性的代码。

​ ③实现结构化(模块化:C语言的模块其实就是多文件+函数)程序设计思想。

​ 关于**结构化设计思想:**将大型的任务划分成相互独立的小型任务模块来设计(多文件+函数)

  • 函数是C语言程序的基本组成单元:

    C语言程序必须包含一个main函数,可以包含零个或多个其他函数。

函数的分类

  • 按来源分:
    • **库函数:**C语言标准库实现必须提供使用函数,如:scanf()、printf()、fgets()、fputs()、strlen()…
    • **自定义函数:**需要程序员实现,开发中大部分函数都是自定义函数。
  • 按参数分:
    • **无参函数:**函数调用时,无需传递参数,可有可无返回值,如:show_all();
    • **有参函数:**函数调用时,需要参数传递数据,经常需要配套返回值来使用,如:printf(“%d\n”,12);
  • 按返回值分:
    • **有返回值函数:**函数执行后返回一个值如:if(scanf("%d",&num) != 1)
    • **无返回值函数(void):**函数执行操作,不返回值
  • 从函数调用角度分析:
    • **主调函数:**主动去调用其他函数的函数。(main函数只能作为主调函数)
    • **背调函数:**被其他函数调用的函数。
  • 举例:
//主调函数
int main()
{
	//背调函数
    printf("hello world !\n");
}

很多时候,尤其是对应自定义函数,一个函数有可能是主调函数,又是背调函数。

int fun_b()
{
    printf("函数B\n");
}

int fun_a()
{
    printf("函数\n");
    // fun_b是被调函数
    fun_b();
}
int main()
{
    // fun_a是被调函数
    fun_a();
}

​ 以上案例中,fun_aO对于fun_bO来说是主调函数,同时对于mainO函数来说,它又是被调函数。

函数的定义

定义

语法:

[返回类型] 函数名([形参列表])      ---函数头 | 函数首部
{
    函数体语句;                  ---函数体:整个{}包裹内容都属于函数体,{}不能省略
}

函数头:

  • **返回类型:**函数返回值类型
  • **函数名:**函数的名称,遵循标识符命名(不能以数字开头,只能包含字母、数字、下划线。建议:小写+下划线,举例:show_all,或者小驼峰命名法第一个单词首字母小写,其他单词首字母大写,举例:showAll()
  • **形参列表:**用于接受主调函数传递的数据,如果有多个参数,使用","分隔,并且每个形参都需要指明类型。

小贴士:

①形参列表(背调函数):主调函数给背调函数传输数据:主调函数→背调函数

②返回类型(背调函数):被调函数给主调函数返回数据:被调函数 → 主调函数

通过生活中的案例理解函数调用:
假设:饮料店的工作人员通过榨汁机榨取新鲜果汁
理解:

工作人员:主调函数

榨汁机:被调函数

水果:传递的参数

果汁:函数的返回值

工作人员向榨汁机放入一个水果:主调函数调用被调函数,并传递数据

工作人员用杯子接收榨汁机榨出的果汁:主调函数接收被调函数返回的数据

说明:

  • 函数的返回类型:就是返回值的类型,两个类型可以不同,但是必须能够进行转换,举例:

    double fun_a()   //函数的返回类型是 double
    {
        return 12;   //函数的返回值是12,其对应的类型是int (return后面跟的是返回值)
    }
    

    以上代码可以理解为:int类型的12赋值给一个double类型的匿名变量(int → double此时属于隐式转换)正确

    double fun_a()   //函数的返回类型是 int
    {
        return 12.5;   
    }
    

    以上代码可以理解为:double类型的12.5赋值给一个int类型的匿名变量(double → int)舍弃
    小数点后的数据。

    范例:

    #include <stdio.h>
    double fun_a()
    {
        return12;//就是将int类型的12赋值给double类型的匿名变量int-->double
    }
    
    int fun_b()
    {
        return12.5;//就是将double类型的12.5赋值给int类型的匿名变量double-->int此时会舍弃掉小数部分
    }
    
    double fun_c()
    {
        return12.5;//就是将double类型的12.5赋值给double类型的匿名变量double-->double
    }
    
    int main(int argc,char *argv[])
    {
        //接收函数返回值,函数返回什么类型,就用什么类型接收
    	double result1= fun_a();//主调函数使用double来接收被调函数返回的double,double -->double
    	printf("‰lf\n",result1);
    	int result2= fun_b();//主调函数使用int来接收被调函数返回的int,int-->int
    	printf("%d\n",result2);
    	int result3 = (int)fun_c(); //主调函数使用int来接收被调函数返回的double,int -->(int)double
    	printf("%d\n" ,result3);
        
    	return 0;
    }
    
  • 在C语言中无返回值时应明确使用void 类型,举例:

    void text()
    {
        printf("hello\n");
    }
    //下面写法等价上面写法
    void text()
    {
        printf("hello\n");
        return;
    }
    
  • 在C语言中C89标准中允许函数的返回值类型标识符可以省略,如果省略,默认返回int。C99/C11标准要求必须明确指定返回类型,不再支持默认int类型,举例:

    //写法1(C98标准):main的返回类型是int类型,默认的返回值是0,等价于写法2   不推荐
    main()
    {
        ...
    }
    //写法2 (C99/C11标准):main的返回值类型是int类型,返回值是0   推荐写法
    int main()
    {
        return 0;
    }
    
  • 函数中返回语句形式return(表达式)或者rwturn 表达式

    //写法1
    int main()
    {
        return (0);
    }
    
    //写法2
    int main()
    {
        return 0;
    }
    
  • 如果参数列表中有多个形式参数,则它们之间要用","分隔;即使它们的类型形同在形式参数中只能逐个进行说明,举例:

    //正确示例
    int avg(int x,int y,int z)
    {
        ...
    }
    
    //错误示例
    int avg(int x, y, z)   //不能省略每个形象的类型
    {
        ...
    }
    
  • 如果 形参列表 中没有参数,我们可以不写,也可以用void标识,举例:

    // 写法1   推荐
    
    int main()
    {
       ...
    }
    
    // 写法2   
    
    int main(void)
    {
       ...
    }
    
案例
案例1
  • 需求:计算1~n之间自然数的阶乘

  • 代码:

    /*************************************************************************
      > File Name:    demo01.c
      > Author:       小刘
      > Description:  
      > Created Time: 2025年05月15日 星期四 09时19分36秒
     ************************************************************************/
    
    #include <stdio.h>
    
    /**
     * 求1~n的阶乘值
     */
    size_t fun_1(int n)
    {
        int i;    //循环变量
        size_t s = 1;//阶乘值,初始值是1
    
        for (i = 1; i <= n; i++) s *= i;
        return s;
    
    }
    
    int main(int argc,char *argv[])
    {
        printf("1~12的阶乘结果是%lu\n",fun_1(12));
        printf("1~20的阶乘结果是%lu\n",fun_1(20));
        printf("1~30的阶乘结果是%lu\n",fun_1(30));
        printf("1~40的阶乘结果是%lu\n",fun_1(40));
        return 0;
    }
    
  • 运行结果

    在这里插入图片描述

注意:这里计算结果为0,是因为数据太大,超过int存储范围,高位数据丢失,低位数据转出来为0,建议

使用 unsigned long 类型。

案例2
  • 需求:计算一个圆台两个面的面积之和。

在这里插入图片描述

  • 代码:

    /*************************************************************************
      > File Name:    demo02.c
      > Author:       小刘
      > Description:  
      > Created Time: 2025年05月15日 星期四 09时36分52秒
     ************************************************************************/
    
    #include <stdio.h>
    #include <math.h>
    
    #define PI 3.1415926
    
    /**
     * 定义一个函数,根据半径计算圆面积
     * @param r: 半径
     * @return 面积
     */
    
    double cicle_area(double r)
    {
        return PI * pow(r,2.0);
    }
    
    
    int main(int argc,char *argv[])
    {
        double r1,r2,area1,area2;
    
        printf("请输入两个圆的半径:");
        scanf("%lf%lf",&r1,&r2);
    
        area1 = cicle_area(r1);
        area2 = cicle_area(r2);
    
        printf("两个圆的面积之和为:%.2lf\n",area1 + area2);
        return 0;
    }
    
  • 运行结果

在这里插入图片描述

  • 编译命令:
gcc demo03.c -lm
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值