05- c语言函数 (C语言)

news2024/9/20 5:57:08

一 函数的概念

1、在程序设计过程中,为了实现某个功能需要编写多行代码,例如求一个二维数组中的最大值,如果 该功能需要被多次使用,我们可以在每次使用时将原来的代码重复编写,但是这样未免有“凑代码”的嫌疑,而且编程效率也不高。为了避免重复劳动,我们可以将这部分代码封装到一个“函数”
中,在需要使用该功能时调用封装好的函数即可。

2、函数就是 具有特殊功能的指令的集合。 
3、C程序是由函数组成的,函数是 C 程序的基本模块,C程序从主函数 main() 开始执行。
4、从函数定义的角度出发,函数可以分为 库函数用户自定义函数 两种。 

  • 库函数:由标准C库提供,用户不需要自己实现,在使用时直接调用即可,例如 printfscanf函数等。
  • 用户自定义函数:需要用户自己根据实际需求自己实现,例如比较两个整数的大小,并且求出最大值

二 函数的定义

2.1 函数定义的语法规则

类型标识符 函数名 (形参列表)
{
函数体
}
说明:

  1. 类型标识符:函数返回数据的类型,支持C语言所有的数据类型
  2. 函数名:由用户定义的标识符
  3. 形参列表:函数用来接收用户所传递数据的参数,参数可以时0个也可以是多个
  4. 函数体:实现函数功能的代码块

2.2 无参函数的定义

1、函数 不需要接收用户传递的数据
类型标识符 函数名()
{
函数体
}
注意:形参列表为空
2、如果函数不需要返回值,”类型标识符“可以设计为 void

void func_1()
{
    printf("hello world\n");
}

3、如果函数需要返回值,返回值是什么类型”类型标识符“就是什么类型,例如:设计一个函数返
回1~100的和。

int func_2()
{
    int i, sum = 0;
    for (i = 1; i <= 100; i++)
        sum += i;
    return sum;
}

2.3 有参函数的定义

1、可以根据实际需求设计函数的形参,形参的作用就是接收用户传递的数据

类型标识符 函数名(类型标识符 形参1, 类型标识符 形参2 ... )
{
函数体
}
注意:形参的数据类型及个数由实际需求而定

2、设计一个函数计算两个整数的和

void sum(int a, int b)
{
    int c = a+b;
    printf("sum: %d\n", c);
}

2.4 函数的参数和返回值

2.4.1 函数的形参实参

1、形参出现在函数的定义中,在整个函数体中都可以访问到,离开了该函数就不能被访问了。

2、实参出现在函数调用时

3、函数调用时,将实参的值的赋值给形参

4、形参和实参有如下特点:

  • 形参只有在函数被调用时才会被分配 内存空间
  • 实参可以是 常量变量表达式函数名

2.4.2 函数的 返回值 

1、函数的返回值是函数将函数体中的 执行结果返回给函数的调用者,通过 return 语句返回。

return 表达式;
或者
return (表达式);

有没有( )都是正确的,为了简明,一般也不写( )。例如:
return max;
return a+b;
return (100+200);

2、函数执行完 return 语句后,函数执行完毕(函数退出)。
3、函数的返回类型就是函数的类型。

例如:int func(){} 该函数的返回类型是int,那我们就说函数func是个 整型函数

4、如果函数不需要返回值,函数的返回类型为void,在函数体中可以使用 "return ;" 语句退出函
数,也可以不使用“return ;”

void func_3()
{
    printf("hello\n");
    return ; //这句话也可以不写
}

5、如果函数返回的类型和return语句中表达式的值的数据类型不一致,则以函数返回类型为准,即函数返回类型决定返回值的类型。对数值型数据可以自动进行类型转换

double max() // 函数的返回类型为double
{
    int a = 1;
    return a;// 返回值a为int类型,会转为double类型再返回,最终返回 1.0
}

三 函数的调用

1、函数在定义完以后,如果不被调用函数是不会被执行到的。
2、main函数是C程序的主函数,是会被自动执行到的,C程序中有且只有一个main函数

3.1 无参函数的调用

1、调用方法

函数名();
或者:
变量 = 函数名();

注意:当函数有返回值时,我们可以定义一个变量来接收函数的返回值,但是定义变量的数据类型必须和函数的返回类型一致,当然我们也可以不接收函数的返回值

2、举例

int func()
{
    return 10;
}

int main()
{
    func();
    int x = func();
    return 0;
}

3.2 有参函数的调用

1、调用方法

函数名(实参列表)
或者
变量 = 函数名(实参列表)

注意:

  • 传递的实参是和形参一一对应的
  • 实参的个数和形参的个数必须一致

3.3 函数的嵌套调用

1、函数的嵌套调用:某个函数的函数体中调用了另外一个函数

void b()
{
    printf("b\n");
}

void a()
{
    printf("a\n");
    b();
}

int main()
{
    a();
    return 0;
}

执行逻辑:

3.4 函数的声明

1、在上一个例子中,如果我们将函数a和b的位置互换,我们编译程序看看会发生什么情况

void a()
{
    printf("a\n");
    b();
}

void b()
{
    printf("b\n");
}

int main()
{
    a();
    return 0;
}

我们发现编译报 warning了,意思时函数b被隐式的声明了

当然,虽然报warning了,但是代码还是能够成功编译,并且能够正常执行。但是,如果是低版本的编译器,可能会编译报错:函数b是未声明的!
注意:编译程序时要将warning当error
为什么程序编译会报warning甚至是error呢?因为编译器在编译代码时,如果代码中有调用函数的
语句,会在该语句之前检索函数是否有被声明或者定义,如果没有则编译报warning或者error!
解决方法:

  • 函数b的定义放在函数a之前
  • 在代码的前面部分对函数b进行声明void b(); 

2、函数声明语法

函数类型 函数名(形参列表);
注意:
1、后面有分号 ;
2、函数声明时,函数类型(返回值类型)必须于函数实现时一致,函数名必须和函数实现时一致
3、形参列表中,可以不填写形参变量的名字,只需要填写形参的类型即可,例如:
int fun(int, float);

四 局部变量和全局变量

4.1 局部变量

1、定义 在{ }内的变量,称之为局部变量

void func()
{
    int func_x = 100; //局部变量
}

int main()
{
    int i = 10;//局部变量
    {
        int i = 100; //局部变量
        int j = 100; //局部变量
    }
    return 0;
}

2、局部变量的作用域:所在的 { } 内

void func()
{
    int func_x = 100; //局部变量
}

int main()
{
    int i = 10;//局部变量
    {
        int i = 100; //局部变量
        printf("%d\n", i); // 100
        int j = 100; //局部变量
    }
    printf("%d\n", i); // 10
    return 0;
}

3、局部变量的生命周期:随 { } 的结束而结束

void func()
{
    int func_x = 100; //局部变量
}

int main()
{
    int i = 10;//局部变量
    {
        int i = 100; //局部变量
        printf("%d\n", i); // 100
        int j = 100; //局部变量
    }
    printf("%d\n", i); // 10
    printf("%d\n", j); //编译报错:error: 'j' undeclared
    printf("%d\n", func_x);//编译报错:error: 'func_x' undeclared
    return 0;
}

4.2 全局变量

1、定义在函数外部的变量称之为:全局变量

int cnt = 10; //全局变量

void func()
{
    int func_x = 100; //局部变量
    cnt++;
}

int main()
{
    func();
    printf("cnt: %d\n", cnt);
    return 0;
}

2、全局变量的初始化

  • 全局变量在定义时如果不初始化,编译器会将值设置为默认值0

3、全局变量的作用域:整个程序
4、全局变量的生命周期:随程序的结束而结束

五 递归函数

5.1 递归函数的定义

1、一个函数在它的 函数体内调用自身称为递归调用,这种函数称为递归函数。
2、举例

void func()
{
    func();
}

5.2 递归函数的使用

1、思考:什么时候需要使用递归函数?
在实现某个函数的过程中,某个功能的实现与本函数一样,则使用函数的递归

2、思考:如果函数的递归调用是这种模式,会出现什么情况?

注意:函数递归调用一定要有退出条件!!!

3、实例:求n的阶乘

long long factorial(int n)
{
    if (n== 1)
        return 1;
    return n*factorial(n-1);
}

4、递归函数的调用流程

  • 逐层调用过程

  • 逐层退出过程 

5、思考:如何使用递归实现求斐波那契数列的第n项的值 

int Fibonacci(int n)
{
    if ((n == 1) || (n == 0))
        return n;
    return Fibonacci(n-2) + Fibonacci(n-1);
}

6、举一反三:求斐波那契数列的前n项的和

#include<stdio.h>
//求斐波那契数列的第n项
unsigned long long fac(int n)
{
    if (n == 1)
        return 1;
    return n*fac(n-1);
}

//求斐波那契数列的前n项的和
/*
* 解题思路:前n项的和 = 第n项 + 前n-1项的和
* */
unsigned long long facSum(int n)
{
    if (n == 1 || n == 0)
        return n;
    return fac(n) + facSum(n-1);
}

int main()
{
    unsigned long long sum;
    int n;
    scanf("%d", &n);
    printf("%lld\n", facSum(n));
    return 0;
}

7、练习

有5个人坐在一起,问第5个人多少岁?他说比第4个人大2岁。问第4个人岁数,他说比第3个人
大2岁。问第3个人,又说比第2个人大2岁。问第2个人,说比第1个人大2岁。最后问第1个人,他
说是10岁。请问第5个人多大。

int age(int n)
{
    if (n == 1)
        return 10;
    return age(n-1) + 2;
}

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

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

相关文章

大数据治理.数据储存技术

hive是基于Hadoop的一个数据仓库工具&#xff0c;用来进行数据提取、转化、加载&#xff0c;这是一种可以存储、查询和分析存储在Hadoop中的大规模数据的机制。hive数据仓库工具能将结构化的数据文件映射为一张数据库表&#xff0c;并提供SQL查询功能&#xff0c;能将SQL语句转…

Spark大数据处理学习笔记(3.8.3) Spark RDD典型案例-利用RDD实现分组排行榜

该文章主要为完成实训任务&#xff0c;详细实现过程及结果见【http://t.csdn.cn/Twpwe】 文章目录 一、任务目标二、准备工作2.1 在本地创建成绩文件2.2 将成绩文件上传到HDFS上指定目录 三、完成任务3.1 在Spark Shell里完成任务3.1.1 读取成绩文件得到RDD3.1.2 利用映射算子生…

Openfire身份认证绕过漏洞复现+利用(CVE-2023-32315)

0x01 产品简介 Openfire是免费的、开源的、基于可拓展通讯和表示协议(XMPP)、采用Java编程语言开发的实时协作服务器。Openfire安装和使用都非常简单&#xff0c;并利用Web进行管理。单台服务器甚至可支持上万并发用户。 0x02 漏洞概述 Openfire的管理控制台是一个基于 Web 的…

自然语言处理从入门到应用——动态词向量预训练:ELMo词向量

分类目录&#xff1a;《自然语言处理从入门到应用》总目录 在双向语言模型预训练完成后&#xff0c;模型的编码部分&#xff08;包括输入表示层以及多层堆叠LSTM&#xff09;便可以用来计算任意文本的动态词向量表示。最自然的做法是使用两个LSTM的最后一层隐含层输出作为词的动…

Qt项目网络聊天室设计

效果演示 网络聊天室 Qt网络聊天室服务端 网络聊天室程序 基于TCP的可靠连接(QTcpServer、QTcpSocket) 一个服务器&#xff0c;多个客户端 3. 服务器接收到某个客户端的请求以及发送信息&#xff0c;经服务器发给其它客户端 最终实现一个共享聊天内容的聊天室&#xff01; …

大数据治理.数据采集/归集技术

第一部分 阿里巴巴DATAx DataX 是阿里开源的一个异构数据源离线同步工具&#xff0c;致力于实现包括关系型数据库(MySQL、Oracle等)、HDFS、Hive、ODPS、HBase、FTP等各种异构数据源之间稳定高效的数据同步功能。 DataX设计理念 DataX本身作为数据同步框架&#xff0c;将不同…

分布式系统消息通信技术:MOM与RPC

一、中间件 什么是中间件 中间件&#xff08;Middleware&#xff09;是处于操作系统和应用程序之间的软件&#xff0c;也有人认为它应该属于操作系统中的一部分。人们在使用中间件时&#xff0c;往往是一组中间件集成在一起&#xff0c;构成一个平台&#xff08;包括开发平台…

springboot配置 spring.profiles.active spring.profiles.include @profile

springboot配置 spring.profiles.active spring.profiles.include profile spring.profiles.active spring.profiles.include profile的命名方式 以 application-开头, --横杠(减号)不能少 application-{这部分自定义}.propertiesapplication-{这部分自定义}.ymlapplicatio…

c++多态详解

前言&#xff1a; 对于面向对象语言来说&#xff0c;多态是面向对象的三大特性之一&#xff0c;简单一点来说多态就是多种形态&#xff0c;是不同对象接收到同一种消息产生的不同动作或者反应&#xff0c;听起来有点抽象&#xff0c;实际上就是完成一个任务让不同的对象来做产生…

合宙Air724UG Cat.1模块硬件设计指南--模拟语音通道

模拟语音通道 简介 模拟音频技术是由传感器采集得到的连续变化的值&#xff0c;根据其电压的幅度用来展示声音强弱。CAT.1内置3种音频输出模式&#xff0c;分别为扬声器(SPK)输出&#xff0c;耳机(HP)输出和听筒(RECEIVER)输出。 特性 SPK接口 SPK-、SPK。Speaker差分信号接口…

记压测环境数据表死锁导致接口长时间pending问题

背景 压测过程中测试小伙伴反映某个页面长时间loading无法打开&#xff0c;接下来我们排查一下&#xff0c;既然是压测环境&#xff0c;那么就需要排除服务器资源层面的因素&#xff0c;现在考验的就是在系统资源不足时系统的情况&#xff0c;那么我们就直接从代码层面开始排查…

PADS-LAYOUT菜单及工具说明

目录 1 材料清单输出 2 元件属性检查 3 材料清单制作 4 原理图生成PDF 4.1PDF文件生成 4.2PDF文件查阅 4.3PDF文件打印 5 PADS转Altium Designer 5 Altium Designer转PADS 5.1 直接导入法 5.2 软件生成法 6 PADS层定义 7 设计规则输出 7.1 PADS对象管理 7.2 PAD…

pandas---分箱(离散化处理)、绘图、交叉表和透视表

1. 分箱 分箱操作就是将连续型数据离散化。分箱操作分为等距分箱和等频分箱. 1.1 等宽分箱 pandas.cut(x, bins, rightTrue, labelsNone, retbinsFalse, precision3, include_lowestFalse, duplicatesraise, orderedTrue) x&#xff1a;要分箱的一维数组或者 Series。 bi…

分布式系统概念和设计——分布式共享内存

分布式系统概念和设计 分布式共享内存 分布式共享内存是在不共享物理内存的计算机之间实现数据的共享的一个抽象。 有一个底层运行的系统保证其透明性&#xff0c;但是进程还是根据内存的分布处理物理内存的分布式能力 DMS最关键点&#xff1a; 不需要关心数据的通信&#xff…

百家号热议排名代发

百家号热议排名代发&#xff0c;百度排名怎么做&#xff0c;有什么技巧或者方式方法吗#百度首页关键词排名#百度推广#百度竞价推广#百度关键词排名#百度首页关键词排名方法# 其实百度推广并不赚钱&#xff0c;也没有你想象中的那么好做。 我说三点&#xff0c; 99% 的用户都遇…

C语言之动态内存分配讲解(2)

动态内存函数的介绍 在开始本章节之前&#xff0c;我们来复习一下动态内存分配&#xff08;1&#xff09;中所讲到的知识&#xff0c;看下面目录一和目录二 为什么存在动态内存分配 我们已经掌握的内存开辟方式有 int val 20;//在栈空间上开辟四个字节 char arr[10] {0};/…

Go语言并发之扇入和扇出

1、Go语言并发之扇入和扇出 编程中经常遇到扇入和扇出两个概念&#xff0c;所谓的扇入是指将多路通道聚合到一条通道中处理&#xff0c;Go 语言最简单的扇入 就是使用 select 聚合多条通道服务&#xff1b;所谓的扇出是指将一条通道发散到多条通道中处理&#xff0c;在Go语言…

揭开视频识别(动作识别)的神秘面纱(附代码和demo)!

PaddleDetection 在计算机视觉中&#xff0c;视频识别和检测是一个重要的方向。历年来CVPR和ICCV等顶会文章中这类论文是最多的。视频识别和检测也是最有落地场景前景的&#xff0c;像人脸识别、动作检测、异常检测、行人重识别、行人计数等都是很有落地前景的应用方向。本文介…

shardingsphere第三课各种功能点及核心源码

一、功能点 1.审计功能 分片审计功能是针对数据库分片场景下对执行的 SQL 语句进行审计操作。分片审计既可以进行拦截操作&#xff0c;拦截系统配置的非法 SQL 语句&#xff0c;也可以是对 SQL 语句进行统计操作。 目前ShardingSphere内置的分片审计算法只有一个&#xff0c;…

C语言指针初进阶知识汇总

目录 1 指针 1.1 指针是乜嘢 1.2 指针的声明 1.3 运算符 1.4 简单的小例子们 1.5 指针的运算 1.5.1 指针加减运算 1.5.2 间址运算 1.5.3 指针的相减 两个地址之间的偏移量 2 指针与数组 2.1 指针和一维数组 2.1.1 定义数组及指针变量 2.1.2 能动手就不要瞎扯 2.…