c语言函数(详解)

目录

前言

一、函数的基本概念和作用

二、函数的声明和定义

三、函数参数的传递方式

四、函数的递归

五、函数指针

总结


前言

本文主要讲解了c语言函数方面的内容


    • 函数的定义和调用
    • 函数的返回值和参数
    • 函数的作用域和生命周期
  1. 函数的声明和定义

    • 函数声明和函数定义的区别
    • 函数声明的语法规则
    • 函数定义的语法规则
  2. 函数参数的传递方式

    • 值传递
    • 引用传递
    • 指针传递
  3. 函数的递归

    • 递归的基本概念和原理
    • 递归函数的编写和调用
    • 递归和迭代的比较
  4. 函数的重载

    • 函数重载的概念和作用
    • 函数重载的语法规则
    • 函数重载的实际应用
  5. 内联函数

    • 内联函数的概念和作用
    • 内联函数的使用方法
    • 内联函数的优缺点
  6. 函数指针

    • 函数指针的概念和作用
    • 函数指针的声明和使用
    • 函数指针和回调函数的应用
  7. 变长参数函数

    • 变长参数函数的概念和作用
    • 变长参数函数的声明和使用
    • 变长参数函数的应用案例
  8. 常见的标准函数库

    • 数学函数库
    • 字符串处理函数库
    • 文件操作函数库
    • 时间和日期函数库
  9. 错误处理和异常处理

    • 错误处理的概念和目的
    • 错误处理的方法和技巧
    • 异常处理的概念和使用方法

一、函数的基本概念和作用

      函数是一段封装了特定功能的代码块。它们用来组织和重用代码,使程序更易于理解和维护。函数可以接受输入参数,并且可以返回一个值。

        函数的定义是指我们编写的函数代码块,它包括函数名、参数列表、返回类型和函数体。函数名用于标识函数,在调用函数时使用。参数列表指定了函数接受的输入参数的类型和名称。返回类型指定了函数返回值的类型。函数体是实际执行的代码。

       函数的调用是指使用函数名和传递给函数的参数列表来执行函数。调用函数时,程序将跳转到函数体,并执行其中的代码。函数执行完毕后,程序将返回到函数调用的位置继续执行。

         函数的返回值用于将结果从函数传递回调用函数的位置。返回值的类型必须与函数的返回类型相符。在函数体中,我们可以使用关键字return来返回一个值。调用函数时,我们可以将返回值赋值给一个变量,或者直接使用返回值。

       函数的参数是在调用函数时传递给函数的值。参数可以是原始数据类型,也可以是对象或数组等复合数据类型。参数在函数体内部作为变量使用。函数可以有多个参数,它们以逗号分隔。

       函数的作用域是指函数体内部定义的变量的可见范围。函数体内部可以访问外部定义的变量,但是外部不能访问函数体内部定义的变量。函数的作用域可以是全局的,也可以是局部的。

       函数的生命周期是指函数在程序中存在的时间段。函数在定义时创建,调用时执行,执行完毕后销毁。函数的生命周期可以由函数的作用域和调用方式决定。

二、函数的声明和定义

       函数的声明和定义指的是在程序中告诉编译器函数的名称、返回类型和参数列表以便在程序中使用该函数的过程。

       函数声明是在程序中使用函数之前告诉编译器函数的名称、返回类型和参数列表。函数声明只是告诉编译器函数的存在,并没有具体的函数体。

        函数定义是在程序中具体实现函数的功能,包括函数的函数体。函数定义提供了函数的实际操作。

函数声明的语法规则: 返回类型 函数名(参数列表);

函数定义的语法规则: 返回类型 函数名(参数列表) { // 函数体 // 函数的实际操作 }

例如,下面是一个函数声明和定义的例子:

函数声明: int add(int a, int b);

函数定义: int add(int a, int b) { return a + b; }

在函数声明中,告诉编译器有一个函数叫做add,返回类型是int,有两个int类型的参数a和b。

在函数定义中,实现了add函数的具体功能,计算a和b的和,并将结果返回。

三、函数参数的传递方式

函数参数的传递方式有三种:

  1. 值传递:将参数的值复制一份传递给函数,在函数内部对参数进行修改不会影响到外部的变量。

  2. 引用传递:将参数的引用(内存地址)传递给函数,函数可以直接修改参数所指向的变量的值,从而影响到外部的变量。

  3. 指针传递:将参数的指针(地址)传递给函数,函数可以通过指针访问并修改参数所指向的变量的值,从而影响到外部的变量。

代码演示:

值传递: #include <stdio.h>

void changeValue(int num) { num = 10; }

int main() { int num = 5; changeValue(num); printf("%d\n", num); // 打印结果是5,num在changeValue函数中的修改不会影响到外部的变量 return 0; }

引用传递: #include <stdio.h>

void changeValue(int* numPtr) { *numPtr = 10; }

int main() { int num = 5; changeValue(&num); // 传递num的地址 printf("%d\n", num); // 打印结果是10,changeValue函数内部修改了num的值 return 0; }

指针传递: #include <stdio.h>

void changeValue(int* numPtr) { *numPtr = 10; }

int main() { int num = 5; int* ptr = # // 声明一个指向int类型的指针,存储num的地址 changeValue(ptr); // 传递指针ptr的值 printf("%d\n", num); // 打印结果是10,changeValue函数内部通过指针修改了num的值 return 0; }
四、函数的递归

       递归的基本概念和原理: 递归是指一个函数调用自己或者调用其他函数时,该函数又调用该函数的过程。它是一种解决问题的有效方法,它把一个大问题分解成了一个或多个相同或相似的子问题,然后递归地解决这些子问题,最后合并得到原问题的解。

        递归函数的编写和调用: 编写递归函数时,需要定义递归函数的终止条件,即递归的基本情况。当递归函数的输入满足终止条件时,递归停止,返回结果。否则,递归函数调用自身,并将问题规模缩小,直到满足终止条件。

       递归和迭代的比较: 递归和迭代都是循环的方法,但它们的实现方式不同。递归是通过函数的调用来实现循环,而迭代是通过循环结构来实现循环。递归的代码通常比迭代的代码简洁,但它的效率较低,因为每次递归都需要调用函数并保存调用的状态。

代码例子:

#include <stdio.h>

int factorial(int n){
    // 终止条件
    if(n == 0){
        return 1;
    }
    // 递归调用
    return n * factorial(n-1);
}

int main(){
    int n = 5;
    int result = factorial(n);
    printf("Factorial of %d is %d\n", n, result);
    return 0;
}

       这段的代码中,factorial函数通过递归的方式计算阶乘。当输入为0时,递归停止,返回结果1。否则,递归调用函数,将问题规模缩小,并与当前的n相乘。最后,递归函数返回结果,得到阶乘的结果。在main函数中,我们调用factorial函数来计算5的阶乘,并打印结果。输出结果为:Factorial of 5 is 120。

五、函数指针

   

      函数指针是指向函数的指针变量。它可以指向特定参数和返回类型的函数,并且可以通过函数指针来调用该函数。函数指针可以被用来作为函数的参数、返回值或者在运行时动态调用函数。

函数指针的声明使用以下语法:

返回类型 (*指针变量名)(参数列表);

其中,指针变量名可以是任意合法的标识符,它指向具有返回类型和参数列表的函数。

函数指针的使用可以通过以下步骤进行:

  1. 声明函数指针,并指定它所指向的函数的返回类型和参数列表。
  2. 将函数的地址赋值给函数指针。
  3. 通过函数指针来调用函数。

代码演示:

#include <stdio.h>

int add(int a, int b) {
    return a + b;
}

int subtract(int a, int b) {
    return a - b;
}

int main() {
    int (*operation)(int, int); // 声明函数指针
    int result;

    operation = add; // 将函数地址赋给函数指针
    result = operation(10, 5); // 通过函数指针调用函数
    printf("Addition result: %d\n", result);

    operation = subtract; // 将另一个函数地址赋给函数指针
    result = operation(10, 5); // 再次通过函数指针调用函数
    printf("Subtraction result: %d\n", result);

    return 0;
}

       函数指针和回调函数的应用是在某个函数中传递另一个函数的指针作为参数,然后在需要的时候调用这个函数指针。这种机制可以实现灵活的函数调用,特别适用于事件驱动的程序设计。

代码示例:

#include <stdio.h>

// 回调函数的定义
void message() {
    printf("Hello, World!\n");
}

// 接受函数指针作为参数的函数
void printMessage(void (*callback)()) {
    callback();
}

int main() {
    // 将回调函数的地址传递给函数指针
    printMessage(message);

    return 0;
}

       以上代码中,printMessage函数接受一个函数指针作为参数,然后在需要的时候调用这个函数指针。在main函数中,将message函数的地址作为参数传递给printMessage函数,从而实现了回调函数的功能。


总结

 以上就是c语言函数的内容啦,后续我会带来更多实用的内容,感兴趣的可以点个赞支持一下!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

“大模型横扫千军”背后的大数据挖掘--浅谈MapReduce

文章目录 O 背景知识1 数据挖掘2 邦费罗尼原则3 TF.IDF4 哈希函数5 分布式文件系统 一、MapReduce基本介绍1. Map 任务2. 按键分组3. Reduce 任务4. 节点失效处理5.小测验&#xff1a;在一个大型语料库上有100个map任务和若干reduce任务&#xff1a; 二、基于MapReduce的基本运…

25美赛ABCDEF题详细建模过程+可视化图表+参考论文+写作模版+数据预处理

详情见该链接&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 25美国大学生数学建模如何准备&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;-CSDN博客文章浏览阅读791次&#xff0c;点赞13次&#xff0c;收藏7次。通过了解比赛基本…

Python:元组构造式和字典推导式

&#xff08;Python 元组构造式和字典推导式整理笔记&#xff09; 1. 元组构造式 1.1 创建元组 使用圆括号&#xff1a; tuple1 (1, 2.5, (three, four), [True, 5], False) print(tuple1) # 输出: (1, 2.5, (three, four), [True, 5], False) 省略圆括号&#xff1a; tup…

appium自动化环境搭建

一、appium介绍 appium介绍 appium是一个开源工具、支持跨平台、用于自动化ios、安卓手机和windows桌面平台上面的原生、移动web和混合应用&#xff0c;支持多种编程语言(python&#xff0c;java&#xff0c;Ruby&#xff0c;Javascript、PHP等) 原生应用和混合应用&#xf…

vue3组件el-table报错

传给table标签的data不是数组就会报错&#xff0c; 摁着商品管理代码找了半天也没发现哪里错了&#xff0c;而且关闭报错表格数据能正常显示&#xff0c; 。。。 最后发现我还有个订单管理页面&#xff0c;这里面的data初始化成ref( )了&#xff0c;把这个组件注释掉&#xf…

基于SpringBoot+WebSocket的前后端连接,并接入文心一言大模型API

前言&#xff1a; 本片博客只讲述了操作的大致流程&#xff0c;具体实现步骤并不标准&#xff0c;请以参考为准。 本文前提&#xff1a;熟悉使用webSocket 如果大家还不了解什么是WebSocket&#xff0c;可以参考我的这篇博客&#xff1a; rWebSocket 详解&#xff1a;全双工…

《边界感知的分而治之方法:基于扩散模型的无监督阴影去除解决方案》学习笔记

paper&#xff1a;Boundary-Aware Divide and Conquer: A Diffusion-Based Solution for Unsupervised Shadow Removal 目录 摘要 1、介绍 2、相关工作 2.1 阴影去除 2.2 去噪扩散概率模型&#xff08;Denoising Diffusion Probabilistic Models, DDPM&#xff09; 3、方…

linux-mysql在centos7安装和基础配置

1.安装mysql数据库 1.使用官网安装 1.检查是否存在mysql的分支mariadb [rootlocalhost ~]# rpm -qa |grep mariadb mariadb-libs-5.5.64-1.el7.x86_64 [rootlocalhost ~]# 2.卸载这个分支包 [rootlocalhost ~]# rpm -qa | grep mariadb mariadb-libs-5.5.64-1.el7.x86_64 …

Python!从0开始学爬虫:(一)HTTP协议 及 请求与响应

前言 爬虫需要基础知识&#xff0c;HTTP协议只是个开始&#xff0c;除此之外还有很多&#xff0c;我们慢慢来记录。 今天的HTTP协议&#xff0c;会有助于我们更好的了解网络。 一、什么是HTTP协议 &#xff08;1&#xff09;定义 HTTP&#xff08;超文本传输协议&#xff…

MySQL数据库笔记——最左前缀原则原理及其注意事项

大家好&#xff0c;这里是Good Note&#xff0c;关注 公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍MySQL索引的关键潜规则——最左前缀原则。 文章目录 图示单值索引和联合索引单值索引联合索引 最左前缀原则示例分析1. 全值匹配查询时2. 匹配左…

Java数据结构 (链表反转(LinkedList----Leetcode206))

1. 链表的当前结构 每个方框代表一个节点&#xff0c;每个节点包含两个部分&#xff1a; 左侧的数字&#xff1a;节点存储的值&#xff0c;例如 45、34 等。右侧的地址&#xff08;如 0x90&#xff09;&#xff1a;表示该节点 next 指针指向的下一个节点的内存地址。 例子中&a…

IMX6ull项目环境配置

文件解压缩&#xff1a; .tar.gz 格式解压为 tar -zxvf .tar.bz2 格式解压为 tar -jxvf 2.4版本后的U-boot.bin移植进SD卡后&#xff0c;通过串口启动配置开发板和虚拟机网络。 setenv ipaddr 192.168.2.230 setenv ethaddr 00:04:9f:…

git基础指令大全

版本控制 git管理文件夹 进入要管理的文件夹 — 进入 初始化&#xff08;提名&#xff09; git init 管理文件夹 生成版本 .git ---- git在管理文件夹时&#xff0c;版本控制的信息 生成版本 git status 检测当前文件夹下的文件状态 (检测&#xff0c;检测之后就要管理了…

[高等数学学习记录]函数的极值与最大值最小值

1 知识点 1.1 函数的极值及其求法 定义 设函数 f ( x ) f(x) f(x) 在点 x 0 x_0 x0​ 的某邻域 U ˚ ( x 0 ) \mathring{U}(x_0) U˚(x0​) 内有定义&#xff0c;如果对于去心邻域 U ˚ ( x 0 ) \mathring{U}(x_0) U˚(x0​) 内的任一 x x x&#xff0c;有 f ( x ) <…

docker 简要笔记

文章目录 一、前提内容1、docker 环境准备2、docker-compose 环境准备3、流程说明 二、打包 docker 镜像1、基础镜像2、国内镜像源3、基础的dockerfile4、打包镜像 四、构建运行1、docker 部分2、docker-compose 部分2.1、构建docker-compose.yml2.1.1、同目录构建2.1.2、利用镜…

JVM常见知识点

在《深入理解Java虚拟机》一书中&#xff0c;介绍了JVM的相关特性。 1、JVM的内存区域划分 在真实的操作系统中&#xff0c;对于地址空间进行了分区域的设计&#xff0c;由于JVM是仿照真实的机器进行设计的&#xff0c;那么也进行了分区域的设计。核心区域有四个&#xff0c;…

电脑系统bcd文件损坏修复方法:小白也会的修复方法

电脑系统bcd文件损坏怎么办?当电脑开机时出现bcd文件损坏&#xff0c;一般情况是由于电脑系统的引导坏了&#xff0c;需要进行修复。现在越来越多的小伙伴遇到电脑引导丢失或者安装后无法正常引导的问题&#xff0c;我们现在一般是pe下进行修复引导&#xff0c;那么电脑系统bc…

Flutter_学习记录_导航和其他

Flutter 的导航页面跳转&#xff0c;是通过组件Navigator 和 组件MaterialPageRoute来实现的&#xff0c;Navigator提供了很多个方法&#xff0c;但是目前&#xff0c;我只记录我学习过程中接触到的方法&#xff1a; Navigator.push(), 跳转下一个页面Navigator.pop(), 返回上一…

【架构面试】二、消息队列和MySQL和Redis

MQ MQ消息中间件 问题引出与MQ作用 常见面试问题&#xff1a;面试官常针对项目中使用MQ技术的候选人提问&#xff0c;如如何确保消息不丢失&#xff0c;该问题可考察候选人技术能力。MQ应用场景及作用&#xff1a;以京东系统下单扣减京豆为例&#xff0c;MQ用于交易服和京豆服…

Git 如何将旧仓库迁移新仓库中,但不显示旧的提交记录

一、异常错误 场景&#xff1a;我想把旧仓库迁移新仓库中&#xff0c;放进去之后&#xff0c;新仓库会显示这个项目之前的所有提交&#xff0c;如何不显示这些旧的提交&#xff1f; 二、原因 我们需要将旧仓库迁移新仓库中&#xff0c;但是又不想在新仓库中显示旧的提交记录…