C语言基础(11)【函数1】

news2025/6/7 1:49:59

内容提要

  • 函数

文章目录

    • 内容提要
    • 函数
      • 函数的描述
      • 函数的分类
      • 相关概念
      • 函数的定义:
        • 定义:
        • 案例:
      • 形参和实参
        • 形参(形式参数)
        • 实参(实际参数)
        • 案例:
      • 函数的返回值
        • 案例:

函数

函数的描述

  • 函数:实现一定功能的,独立的代码模块。我们的函数一定是先定义,后使用
  • 使用函数的优势:
    • 我们可以通过函数提供功能给别人使用。当然我们也可以使用别人提供的函数,减少代码 量。
    • 借助函数可以减少重复性的代码。
    • 实现结构化(模块化)程序设计思想。
    • 关于结构化设计思想:将大型的任务功能划分为相互独立的小型的任务模块来设计。
  • 函数是C语言程序的基本组成单元:
    • C语言程序是由一个(必然是main函数)或多个函数组成。

函数的分类

  • 从函数实现的角度:
    • 库函数:C语言标准库实现的并提供使用的函数,比如常见的有 scanf(),printf(),strlen()…
    • 自定义函数:需要程序员自行实现,开发中大部分函数都是自定义的。
  • 从函数的角度来说:
    • 无参函数:函数调用是,无需传递,可有可无返回值,举例:test1();
    • 有参函数:函数调用时,需要参数传递数据,经常需要配套返回值来使用,举例: printf(“%d”,12);

相关概念

  • 主调函数与被调函数:

    • 主调函数:主动去调用其他函数的函数。

    • 被调函数:被其他函数调用的函数。

    • 举例:

      // 这里的main函数就是 主调函数
      int main()
      {
          // 这里的printf函数就是 被调函数
          printf("hello world!\n");
      }
      
      
    • 很多时候,尤其是对于自定义函数来说,一个函数有可能既是主调函数,又是被调函数。

      int fun_b()
      {
          printf("函数B\n");
      }
      int fun_a()
      {
          printf("函数A\n");
          fun_b();
      }
      int main()
      {
          fun_a();
      }
      	//以上案例中,fun_a()对于fun_b()来说是主调函数,同时对于main()来说,它又是被调函数。
      

函数的定义:

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

函数头:

  • 返回值:函数返回值的类型
  • 函数名:函数的名称,遵循标识符的命名,(不能以数字开头,只能包含字母、数字、下划线,建 议:小写+下划线命名法,举例:set_count() )
  • 形参列表:用于接收主调函数传递的数据,如果有多个参数,使用 , 分隔,且每一个形参都需 要指明类型

说明:

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

    double fun_a()   // 返回类型:double
    {
        return 12;   // 返回值类型:int
    }
    // 相当于 将int类型的12赋值给了double类型的匿名变量,此时转换属于自动类型转换
    dobule res = fun_a()
    
  • 在C语言中还可以定义无类型(即void类型)的函数,这种函数不返回函数值(没有返回值), 只是完成某种功能,举例:

    void test()  // 此时这个函数,没有返回值
    {
        printf("hello\n");
    }
    
    
  • C语言中,函数的返回类型标识符是可以省略的,如果省略,默认返回int,举例:

// 写法1:main的返回类型是int类型,默认的返回值类型是0
main()
{
    
}
// 写法2:等价于写法1,返回值类型是int类型,返回值是0
int main()
{
    return 0; // 如果返回类型是int,这里return 0 不写,也是返回0
}
  • 函数中返回的类型为return(表达式)或者return 表达式其作用是将表达式的值作为 函数值返回给主调函数,其中表达式的类型应该与函数类型一致(也就是说函数类型和返回值 类型之间是支持隐式转换或者显示转换)

    // 写法一
    int main()
    {
        return(0);
    }
    // 写法二
    int main()
    {
        return 0; // 推荐
    }
    
    
  • 如果 ``参数列表 中有多个形式参数,则它们之间要用 , `分隔,举例:

    int avg(int x, int y, int z)
    {
       ...
    }
    
  • 如果形参列表中有多个形参,即使他们的类型是相,在形参列表中只能逐个进行说明。

    int avg(int x, int y, int z)
    {
       ...
    }
    
    
  • 如果形参列表中没有参数,我们可以不写,也可以用void来表示,举例:

    // 写法一
    int main(){..}  // 推荐
    // 写法二
    int main(void){..}
    
  • 一个完整C程序中的所有函数可以放在一个文件中,也可以放在多个文件中,举例:

    • 同一个文件:

      #include <stdio.h>
      void show()
      {
          printf("hello\n");
      }
      int main()
      {
          show();
      }
      
    • 在不同的文件中:

      a.h

      void show();	//头文件中只放函数的声明,也就是说只有函数的头
      

      a.c

      #include "a.h"	 // 引入库函数,使用<>引入头文件;引入自定义函数,使用""引入头文件;
      void show()
      {
          printf("hello\n");
      }
      

      b.c

      #include "a.h"
      int main()
      {
          show();
      }
      
案例:

案例1:

  • 需求:计算1~n之间自然数的阶乘
  • 代码:
/*************************************************************************
  > File Name:    demo01.c
  > Author:       袁厚锋
  > Description:函数案例:求:1~n之间的自然数的阶
  值
  > Created Time: 2025年05月14日 星期三 10时29分03秒
 ************************************************************************/

#include <stdio.h>
/*
 *求1~n的阶乘
 *建议:我们设计的函数,尽量让被调函数的改动较小,由主调函数去影响
 */
long fun_1(int n)
{
    int i ;     //创建循环变量;
    long s  = 1 ;//阶乘的值;
    for(i = 1;i <= n;i++)
    {
        s*=i;
    }
    return s;   //将值返回给主调函数
}
 int main(int argc,char *argv[])
{
    printf("1~5的阶乘结果是:%ld\n",fun_1(5));
    printf("1~10的阶乘结果是:%ld\n",fun_1(10));
    return 0;
}

案例:

  • 需求:计算一个圆台两个面积之和

  • 代码:

    /*************************************************************************
      > File Name:    demo02.c
      > Author:       袁厚锋
      > Description:函数案例:计算一个圆台的两个面积之和  
      > Created Time: 2025年05月14日 星期三 10时52分55秒
     ************************************************************************/
    #include <stdio.h>
    #define PI 3.1415926
    /*
     *定义一个函数根据半径计算面积
     *r:半径
     *return 面积
     */
    double circle_area(double r)
    {
        return PI*r*r;    
    }
    
    int main(int argc,char *argv[])
    {
    //定义两个半径,两个面积
        double r1,r2,area1,area2;
        printf("请输入两个圆形的半径:\n");
        scanf("%lf,%lf",&r1,&r2);
        //调用函数计算圆形的面积
        area1 = circle_area(r1);
        area2 = circle_area(r2);
        printf("一个圆台的两个圆形的面积之和是:%.2lf\n",area1+area2);
        return 0;
    }
    

    形参和实参

    形参(形式参数)

函数定义时,指定的参数,形参是用来接收数据的,函数定义时,系统不会为形参申请内存,只有当函数被调用时,系统才会为形参开辟内存,主要用于存储实际的数据,并且当函数返回时,系统会自动 回收为形参申请的内存资源。(本质上所有函数都有一个return,只不过当我们的函数返回类型是 void类型的时候,return是隐式)

//关于默认的return
void fun1()
{
    //此时return是不建议写出来的,这时候的return;隐式的
}
fun2
{
    //默认为return 0;这里建议写出来
}
//关于函数的跳出处理
void fun3(int n)
{
    if(n % 2 == 0)
    {
        printf("%d是一个偶数!\n",n);
        return;
    }
    printf("%d是一个奇数!\n",n);
}

int fun4(int n)
{
    if(n % 2 == 0)
    {
        printf("%d是一个偶数!\n",n);
        return -1;
    }
    printf("%d是一个奇数!\n",n);
    return 0;
}
实参(实际参数)
  • 函数调用时主调函数传递的数据参量(常量、符号常量、变量、表达式,只要有确定的值),实参就是传递的数据。
  • 实参和形参必须类型相同,如果类型不同按照赋值的规定进行强制转换。
  • 在C语言中,参数的传递必须遵循单项值传递,实参只是将自己的值传给形参,而不是实参本身。形参的值的改变不会影响但实参。
int fun(int n)
{
    printf("%d\n",n);//10;
}
int main()
{
    int a = 10;
    fun(a);	//这里的意思是将a的值拷贝了一份副本传递给形参n
    a = 20;
    return 0 ;
}
  • 实参与形参在内存中占据不停的存储空间(建议实参和形参的名字是一致的)
double fun(double a,double b)
{
    return a + b;
}
int main()
{
    int x = 12,int y = 13;
    int c = (int)fun(x ,y)
}
案例:

案例1:

  • 需求:输入两个整数,用一个函数求出最大值

  • 代码:

    #include <stdio.h>
    /*
    定义一个函数求两个中的最大值
    x,y外部传入的整数
    最大值
    */
    int max(int x,inty)
    {
        return x >y ? x :y;
    }
    int main()
    {
        int a,b,c;
        printf("请输入第1个数!!\n");
       	if(scanf("%d",&a)!= 1);
        {
            //清楚缓冲
            while(getchar()!='\n');
            printf("输入有误!\n");
            return -1;
        }
        printf("请输入第2个数:\n");
       	if(scanf("%d",&b)!=1)
       {
            // 清除缓冲
            while(getchar()!='\n');
            printf("输入有误!\n");
    	return -1;
        }
        //求最大值:
        //用变量接收最大值
        c = max(a,b);
        printf("%,%d中最大的值是:%d\n",a,b,c);
        
        return 0;
    }
    

函数的返回值

  • 若不需要返回值,函数可以没有return语句
// 这种写法,没有返回值 return;
void fun1()
{
    
}
// 这种写法,有返回值,返回 return 0
int fun2()
{
    
}
// 这种写法,有返回值,返回 return 0
fun3()  // 返回类型标识符如果不写,默认是int
{
    
}
  • 一个函数中可以有多个return语句,但任一时刻只有一个return语句被执行

    int eq(int num)
    {
        if(num % 2 == 0)
        {
            printf("%d是偶数\n",num);
            return 0;
        }
        printf("%d是奇数\n",num);
        return 0;
    }
    
  • 被调函数返回给主调函数结果数据(可以是==变量、常量、表达式…,==只要是确定值就可以了。

    int fun1(int a,int b)
    {
        return a + b;	//返回表达式,表达式的计算结果是int
    }
    int fun2(int num)
    {
        if(num %2 == 0)
        return 0;	//如果num 是一个偶数,那么就返回一个0;
        
        return -1;//如果num不是一个偶数,那么就返回一个 1-1;
    }
    
  • 返回值类型一般情况下要和函数中return语句返回的数据类型一致,如果不一致,以函数定时 指定的返回类型为标准。也就是返回值类型和实际返回值的类型可以存在转换转换关系,一般 是将 返回值类型返回类型

案例:
  • 需求:输入两个整数,要求用一个函数求出最大值

  • 案例1

#include <stdio.h>
/**
 * 定义一个函数,求两个数中的最大数
 * @param x,y:外部传入的整数
 * @return 最大值
 */
int max(int x,int y)
{
    if (x > y)
        return x;
    return y;
}
int main(int argc,char *argv[])
{
    int a,b,c;
    
    printf("请输入第1个数:\n");
    if(scanf("%d",&a)!=1)
   {
        // 清除缓冲
        while(getchar()!='\n');
        printf("输入有误!\n");
        return -1;
   }
    printf("请输入第2个数:\n");
    
    if(scanf("%d",&b)!=1)
   {
        // 清除缓冲
        while(getchar()!='\n');
        printf("输入有误!\n");
        return -1;
   }
    // 求最大值
    c = max(a,b);
    printf("%d,%d中的最大值是%d\n",a,b,c);
    return 0;
}
    
  • 案例2:
#include <stdio.h>
/**
 * 定义一个函数,求两个数中的最大数
 * @param x,y:外部传入的整数
 * @return 最大值
 */
double max(int x,int y)
 {
    if (x > y)
        return x;
    return y;
}
int main(int argc,char *argv[])
{
    int a,b,c;
    
    printf("请输入第1个数:\n");
    if(scanf("%d",&a)!=1)
   {
        // 清除缓冲
        while(getchar()!='\n');
        printf("输入有误!\n");
        return -1;
   }
    printf("请输入第2个数:\n");
    
    if(scanf("%d",&b)!=1)
   {
        // 清除缓冲
        while(getchar()!='\n');
        printf("输入有误!\n");
        return -1;
   }
    // 求最大值
    c = (int)max(a,b);
    printf("%d,%d中的最大值是%d\n",a,b,c);
    return 0;
}
  • 案例3:
#include <stdio.h>
int max(int x,int y)
{
    double z;
    z = x > y ? x : y;
    return (int)z;
}
int main(int argc,char *argv[])
{
    int a,b,c;
    
    printf("请输入第1个数:\n");
    if(scanf("%d",&a)!=1)
   {
        // 清除缓冲
        while(getchar()!='\n');
        printf("输入有误!\n");
        return -1;
   }
 printf("请输入第2个数:\n");
    
    if(scanf("%d",&b)!=1)
   {
        // 清除缓冲
        while(getchar()!='\n');
        printf("输入有误!\n");
        return -1;
   }
    // 求最大值
    c = max(a,b);
    printf("%d,%d中的最大值是%d\n",a,b,c);
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2400667.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

R语言基础| 下载、安装

在此前的单细胞教程中&#xff0c;许多小伙伴都曾因为R语言基础不足而十分苦恼。R语言是一种开源的编程语言和软件环境&#xff0c;专门用于统计分析、图形表示和数据挖掘。它最初由Ross Ihaka和Robert Gentleman在1993年创建&#xff0c;旨在为统计学家和数据分析师提供一个广…

微软的新系统Windows12未来有哪些新特性

在今年即将到来的重大设计升级中,苹果计划对其全线操作系统统一按年份命名,作为另一巨头微软的win12还远吗?win11和win10是微软现在正在用的主流版本,win11系统发布于2021年6月24日,win10系统发布于2015年7月29日。预计win12尝鲜版可能在2025年下半年或明年。 尽管win12还…

在虚拟宇宙中低语——进程间通信,Linux命名管道的前世今生

文章目录 &#x1f30c; 序章&#x1f320; 一、命名管道的宿命与哲学1.1、创建及简单使用1.2、命名管道的工作原理1.3、命名管道与匿名管道的区别 2、命名管道的特点及特殊场景2.1、特点2.2、四种特殊场景 3、命名管道实操3.1、实现文件拷贝3.2、实现进程控制 小结 &#x1f3…

STM32的ADC简介

一、ADC简介 STM32的ADC是一种12位逐次逼近型模拟数字转换器。它具备18个通道&#xff0c;能够测量16个外部信号源以及2个内部信号源。各通道的A/D转换可以执行单次、连续、扫描或间断模式。转换结果可采用左对齐或右对齐的方式&#xff08;12位&#xff09;存储于16位数据寄存…

Bash shell四则运算

文章目录 四则运算1. ‌expr 命令‌2. ‌$(( )) 表达式&#xff08;推荐&#xff09;‌3. ‌$[ ] 表达式&#xff08;已弃用&#xff09;‌4. ‌let 命令‌小数运算i 和 i 区别 四则运算 算术运算&#xff1a; - * / %&#xff08;取模&#xff0c;求余数&#xff09; Bash sh…

(javaSE)Java数组进阶:数组初始化 数组访问 数组中的jvm 空指针异常

数组的基础 什么是数组呢? 数组指的是一种容器,可以用来存储同种数据类型的多个值 数组的初始化 初始化&#xff1a;就是在内存中,为数组容器开辟空间,并将数据存入容器中的过程。 数组初始化的两种方式&#xff1a;静态初始化&#xff0c;动态初始化 数组的静态初始化 初始化…

力扣刷题Day 70:在排序数组中查找元素的第一个和最后一个位置(34)

1.题目描述 2.思路 方法1&#xff08;自己写的&#xff09;&#xff1a;一次二分查找找到等于target的一个元素索引axis&#xff0c;然后向左右延伸找边界。 方法2&#xff08;灵茶山艾府佬的闭区间二分查找写法&#xff09;&#xff1a;定义一个lower_bound()函数找到第一个…

图片压缩工具 | 图片属性详解及读取解析元数据

ℹ️ 图片信息及属性 基本属性 格式类型&#xff1a;JPEG、PNG、GIF、WEBP、BMP、TIFF等文件大小&#xff1a;以KB、MB等为单位的存储空间占用创建/修改日期&#xff1a;文件的元数据时间戳 视觉属性 尺寸/分辨率 宽度&#xff08;像素&#xff09;高度&#xff08;像素&…

C# Onnx 动漫人物人脸检测

目录 效果 模型信息 项目 代码 下载 参考 效果 模型信息 Model Properties ------------------------- stride&#xff1a;32 names&#xff1a;{0: face} --------------------------------------------------------------- Inputs ------------------------- name&am…

C++内存列传之RAII宇宙:智能指针

文章目录 1.为什么需要智能指针&#xff1f;2.智能指针原理2.1 RAll2.2 像指针一样使用 3.C11的智能指针3.1 auto_ptr3.2 unique_ptr3.3 shared_ptr3.4 weak_ptr 4.删除器希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力&#xff01; 智能指针是 C 中用于自动…

PVE 虚拟机安装 Ubuntu Server V24 系统 —— 一步一步安装配置基于 Ubuntu Server 的 NodeJS 服务器详细实录1

前言 最近在基于 NodeJS V22 写一个全栈的项目&#xff0c;写好了&#xff0c;当然需要配置服务器部署啦。这个过程对于熟手来说&#xff0c;还是不复杂的&#xff0c;但是对于很多新手来说&#xff0c;可能稍微有点困难。所以&#xff0c;我把整个过程全部记录一下。 熟悉我…

TDengine 开发指南——高效写入

高效写入 本章内容将介绍如何发挥 TDengine 最大写入性能&#xff0c;通过原理解析到参数如何配置再到实际示例演示&#xff0c;完整描述如何达到高效写入。 为帮助用户轻松构建百万级吞吐量的数据写入管道&#xff0c;TDengine 连接器提供高效写入的特性。 启动高效写入特性…

Linux kill 暂停命令

暂停进程 kill -19 在一台服务器上部署了360Pika服务&#xff0c;先用RedisClient连接一下&#xff0c;可以连接 现在暂停进程 暂停后发现再次连接无法连接 恢复进程 kill -18 恢复后可连接

2.0 阅读方法论与知识总结

引言 本文将详细分析考研英语阅读做题步骤&#xff0c;并对方法论进行总结&#xff0c;最后通过真题练习巩固方法。 一、做题步骤 所有技巧都建立在精读真题的基础上&#xff01;建议按以下节奏复习&#xff1a; 1️⃣ 做题 先看题干了解文章大致主旨&#xff08;看看有没有…

5. Qt中.pro文件(1)

本节主要讲.pro文件的作用和一些相关基础知识与操作。 本文部分ppt、视频截图原链接&#xff1a;[萌马工作室的个人空间-萌马工作室个人主页-哔哩哔哩视频] 1 PRO文件 1.1 pro文件作用 添加需要用到的QT模块&#xff0c;如通过QT module_name来添加需要用到的Qt模块。指定生…

简数采集技巧之快速获取特殊链接网址URL方法

简数采集器列表页提取器的默认配置规则&#xff1a;获取a标签的href属性值作为采集的链接网址&#xff0c;对于大部分网站都是适用的&#xff1b; 但有些网站不使用a标签作为链接跳转&#xff0c;而用javascript的onclick事件替代&#xff0c;那列表页提取器的默认规则将无法获…

AI 如何改变软件文档生产方式?

现代软件工程中的文档革命&#xff1a;从附属品到核心组件的范式升级 在数字化转型浪潮席卷全球的当下&#xff0c;软件系统的复杂度与规模呈现指数级增长。据Gartner最新研究显示&#xff0c;超过67%的企业软件项目延期或超预算的根本原因可追溯至文档系统的缺陷。这一现象在…

激光干涉仪:解锁协作机器人DD马达的精度密码

在工业4.0的浪潮中&#xff0c;协作机器人正以惊人的灵活性重塑生产线——它们与工人并肩作业&#xff0c;精准搬运零件&#xff0c;完成精密装配。还能协同医生完成手术&#xff0c;甚至制作咖啡。 标准的协作机器人关节模组由角度编码器、直驱电机(DD马达)、驱动器、谐波减速…

HOPE800系列变频器安装到快速调试的详细操作说明

以下是HOPE800系列变频器从安装到调试的详细操作说明及重要参数设置&#xff0c;适用于工程技术人员或具备电气基础的操作人员。请严格遵循安全规范操作。 以下面电机铭牌为例&#xff1a; HOPE800变频器安装与调试指南** &#xff08;安全第一&#xff01;操作前务必断电并确…

vCenter与ESXi主机每分钟周期性断连修复

问题概述 最近我的测试服务器借给客户用作临时中转&#xff0c;仅更改了ESXi的管理IP&#xff0c;设备拿回来改回原来IP&#xff0c;vCenter开启后重新接收证书&#xff0c;主机和所有VM管理运行正常&#xff0c;跑着跑着发现主机和vCenter会频繁断开连接后又马上自动恢复&…