目录

前言

一、什么是函数

二、函数的构成

三、函数的调用和声明

四、函数的参数

五、函数的递归

总结

写在后面


前言

最近帮家里的小朋友整理一些学习C语言的知识点

有整体入门基础文章——【C语言】拯救新手,半小时从零到一认识C语言基础

C语言数据类型的详解——【C语言】数据类型一文详解

变量和赋值的详解——【C语言】变量及赋值

指针和数组关系——【C语言】小妹不懂指针和数组的关系?那就安排指针数组关系详解

问了小妹她C语言还有哪些不懂得,提到了函数的应用,那么就安排函数的详解。

一、什么是函数

函数是由一系列语句组合而成的,是一组语句的封装。函数的使用可以让我们避免重复的代码编写,让我们的程序更加的模块化。

其实,咱们从接触C语言开始的时候,就已经接触了函数了。每个C语言程序至少会有一个函数,那就是main()函数。main()函数是C语言程序的入口。除了main()函数,咱们在输出的控制台信息的时候用到的printf()也是一个函数。

函数还有很多叫法,比如方法、子例程或程序,等等。

二、函数的构成

函数是由函数类型,函数名,形参列表,函数主体这几部分构成的。

函数类型 函数名(形参列表){

函数主体;

}

  • 函数类型,决定了函数最后return的返回值类型,比如是int型函数,那么在函数体里面要用return返回int型的值,如果是char型函数,则返回char型的值。如果不需要返回值的话,则函数类型写为void
  • 函数名,是我们在调用函数时使用的,就跟变量名一个道理
  • 参数列表,咱们在调用函数时,往函数里面传入的参数,这里的参数是可有可无的,写在函数定义的参数列表的参数叫做形式参数(形参),当我们调用函数的时候,填入的叫实际参数(实参)
  • 函数主体,用花括弧{}括起来的,包含所有组成函数的语句。如果函数不是void型的,则函数主体里面要有return语句返回对应类型的值

三、函数的调用和声明

函数的调用方式:

函数名(实参列表);

这里的实参列表,可以是变量(包括普通变量和指针变量),常量,表达式,函数等。实参列表里多个实参之间用逗号【,】来隔开。当定义函数时没有形参列表,则在调用函数的时候也不用传入实参。

在咱们最熟悉的输出语句printf()就是函数的调用,例如

char str[] = "Hello Baiyu";
printf("%s\n",str);//调用printf()函数,里面的"%s\n",str就是实际参数
  • “%s\n”这个是常量
  • str这个是字符串变量

下面用代码演示一下函数的定义、以及几种函数的调用形式:

#include<stdio.h>//此处定义一个比较两个数取最大值函数
int max(int x, int y) {if (x > y) {return x;}else {return y;}
}//定义一个无返回值类型的函数,用于调用max()函数输出最大值
void output(){int i_baiyu = 10;int i_zhh = 20;// 函数作为表达式的一部分int i_max = max(i_baiyu, i_zhh);int i_max2 = max(i_zhh, i_baiyu) + 100;// 函数作为自身函数的实参,同时函数也作为表达式的一部分int i_max3 = max(max(i_zhh, i_baiyu), i_max2);// 函数作为一个单独语句printf("i_max的值为:%d\n", i_max);printf("i_max3的值为:%d\n", i_max3);//函数作为调用另一个函数时的实参printf("函数作为调用另一个函数时的实参:%d\n", max(max(i_zhh, i_baiyu), i_max2));
} //主函数
int main() {output();return 0;
}

由于C语言代码是从上往下依次执行的,所以对于函数的调用,咱们有两种方式

  1. 函数定义在函数调用之前,函数可以直接调用。
  2. 函数定义在函数调用之后,则需要在函数调用之前先声明被调用的函数之后再调用。

上面这两句话可能看起来有点绕。不能理解,那我们把上面这个比较大小的代码稍微调整一下,把函数定义放在main()函数后面

#include<stdio.h>//主函数
int main() {output();return 0;
}//输出最大值
void output(){int i_baiyu = 10;int i_zhh = 20;// 函数作为表达式的一部分int i_max = max(i_baiyu, i_zhh);int i_max2 = max(i_zhh, i_baiyu) + 100;// 函数作为自身函数的实参,同时函数也作为表达式的一部分int i_max3 = max(max(i_zhh, i_baiyu), i_max2);// 函数作为一个单独语句printf("i_max的值为:%d\n", i_max);printf("i_max3的值为:%d\n", i_max3);//函数作为调用另一个函数时的实参printf("函数作为调用另一个函数时的实参:%d\n", max(max(i_zhh, i_baiyu), i_max2));
} //此处定义一个比较两个数取最大值函数
int max(int x, int y) {if (x > y) {return x;}else {return y;}
}

这个时候,我们执行程序可能会发现其编译时会有告警,这是因为我们的函数定义放在了函数调用之后。函数在调用的时候找不到函数的定义。

因此,我们只需要在函数调用之前,对函数进行声明,这样子的话,函数定义就可以放在程序的任意位置了。

函数的声明格式如下:

函数类型 函数名(形参列表);

我们发现,函数声明跟函数定义差不多,只是把函数定义时的函数体去掉。

修改后的代码如下:

#include<stdio.h>
void output(); //这里增加output函数的声明
int max(int x, int y);//这里增加max函数的声明//主函数
int main() {output();return 0;
}//输出最大值
void output(){int i_baiyu = 10;int i_zhh = 20;// 函数作为表达式的一部分int i_max = max(i_baiyu, i_zhh);int i_max2 = max(i_zhh, i_baiyu) + 100;// 函数作为自身函数的实参,同时函数也作为表达式的一部分int i_max3 = max(max(i_zhh, i_baiyu), i_max2);// 函数作为一个单独语句printf("i_max的值为:%d\n", i_max);printf("i_max3的值为:%d\n", i_max3);//函数作为调用另一个函数时的实参printf("函数作为调用另一个函数时的实参:%d\n", max(max(i_zhh, i_baiyu), i_max2));
} //此处定义一个比较两个数取最大值函数
int max(int x, int y) {if (x > y) {return x;}else {return y;}
}

四、函数的参数

前面咱们说过,函数的形式参数列表,可以是变量(包括普通变量指针变量),常量,表达式,函数等。实参列表里多个实参之间用逗号【,】来隔开

这里单独要再强调一下,就是形参就像是函数内其他的局部变量一样。在函数调用结束之后,会进行销毁。我们在向函数传递变量时,会有两种传递参数形式。这也是为啥前面我在变量那里会强调指出有普通变量跟指针变量

  1. 传值调用:该方法会把实际参数的值复制到函数的形式参数,此时,修改函数内形式参数的值并不会影响实际参数的值
  2. 引用调用:通过指针变量来传递,形参会指向实参地址的指针,当对形参指向的值进行操作时,就相当于对实参本身进行操作

上面这样子讲可能不太好理解,还是上代码

这里咱们举一个例子就是来写一个函数,用于交换两个变量的值。

#include <stdio.h>
// 通过普通变量,进行值传递
void swap(int x, int y) {printf("交换前x的值为:%d,y的值为:%d\n", x, y);int temp = x;x = y;y = temp;printf("交换后x的值为:%d,y的值为:%d\n", x, y);
}
// 通过指针变量,进行引用传递
void swap_p(int* x, int* y) {printf("交换前x的值为:%d,y的值为:%d\n", *x, *y);int temp = *x;*x = *y;*y = temp;printf("交换后x的值为:%d,y的值为:%d\n", *x, *y);}int main() {int i_baiyu = 66;int i_zhh = 77;printf("swap交换前i_baiyu的值为:%d,i_zhh的值为:%d\n", i_baiyu,i_zhh);swap(i_baiyu, i_zhh);printf("swap交换后i_baiyu的值为:%d,i_zhh的值为:%d\n", i_baiyu,i_zhh);printf("-------------------------------------------\n");printf("swap_p交换前i_baiyu的值为:%d,i_zhh的值为:%d\n", i_baiyu, i_zhh);swap_p(&i_baiyu, &i_zhh);printf("swap_p交换后i_baiyu的值为:%d,i_zhh的值为:%d\n", i_baiyu, i_zhh);return 0;
}

五、函数的递归

在开始讲函数的递归之前,给大家将一个耳熟能详的故事

从前有座山,山里有座庙,庙里有个老和尚给一个小和尚讲故事,讲什么呢?老和尚说

从前有座山,山里有座庙,庙里有个老和尚给一个小和尚讲故事,讲什么呢?老和尚说

从前有座山,山里有座庙,庙里有个老和尚给一个小和尚讲故事,讲什么呢?老和尚说

......

在C语言中,当函数直接或者间接调用函数本身,就叫做函数的递归。

在使用函数递归的时候,我们要注意设置好一个从函数退出的条件,否则就会进入一个死循环,就像老和尚给小和尚讲故事一样,是无限循环的。

函数的递归,这样子讲可能不太容易懂,下面举几个例子,让大家一起熟悉一下

通过递归求n的阶乘

我们从数学公式可知

n! = n *(n-1)!

#include <stdio.h>double factorial(unsigned int i)
{if (i <= 1)//这里就是结束递归的判断条件{return 1;}return i * factorial(i - 1);
}
int  main()
{int i_baiyu = 6;// 这里我们计算6的阶乘。printf("%d 的阶乘为 %f\n", i_baiyu, factorial(i_baiyu));return 0;
}

6!= 6 * 5 * 4 * 3 * 2 * 1 = 720

总结

本文讲述了C语言函数的定义、基本使用,和函数的递归。从零到一带各位同学熟悉C语言中函数的使用。

写在后面

如果觉得有用的话,麻烦动动各位发财的小手指,给个一键三连支持一下攻城狮白玉,并把本文分享给更多的小伙伴。你的简单支持,我的无限创作动力

如果有想看的内容,也可以在博文底部评论,我会整理出来给到大家~

【C语言】函数详解(入门到进阶)相关推荐

  1. C 语言教程详解——入门到精通

    C 语言是一种通用的.面向过程式的计算机程序设计语言.1972 年,为了移植与开发 UNIX 操作系统,丹尼斯·里奇在贝尔电话实验室设计开发了 C 语言. C 语言是一种广泛使用的计算机语言,它与 J ...

  2. C语言指针详解——入门C语言指针,初级指针使用。

    原文地址:我的个人博客点击查看 C语言教程第二弹--指针详解 所有学过C语言的人都知道,C语言难在它的指针的使用和理解,今天,我带给大家C语言的指针的教程,供大家学习交流,如果有讲的不对的地方,请给作 ...

  3. 【C 语言】C 语言 函数 详解 ( 函数本质 | 顺序点 | 可变参数 | 函数调用 | 函数活动记录 | 函数设计 ) [ C语言核心概念 ]

    相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...

  4. c语言函数详解1——自定义函数

    这篇文章理论性知识比较多,不过对于初学者对于函数的理解会有更深层次的帮助 目录 c语言的函数--子程序 自定义函数 c语言的函数--子程序 *是大型程序中的某部分代码,由一个或者多个语句组成,她负责完 ...

  5. C语言-入门级别函数详解

    C语言-入门级别函数详解 写在开始 关于函数 1. 函数的定义形式 2.函数的声明 3. 返回语句 4.函数参数 4.1 形式参数(传值调用) 4.2 实际参数(传址调用) 4.3无参数 5.函数的调 ...

  6. 【C语言学习笔记】SWAP函数详解

    SWAP函数详解 本篇文章通过swap函数来深入了解C语言中函数的用法,与指针的应用.参考资料来源于经典书籍与技术博客的分享. 在复习完生存期相关的知识点后(详情可转至此处),初步认识了函数与本地变量 ...

  7. 【Python入门】Python之OS模块39个常用函数详解

    os,语义操作系统,所以该模块就是操作系统相关的功能了,用于处理文件和目录这些我们日常手动需要做的操作,比如新建文件夹.获取文件列表.删除某个文件.获取文件大小.重命名文件.获取文件修改时间等,该模块 ...

  8. c++ memset 语言_C/C++ 中memset() 函数详解及其作用介绍

    memset 函数是内存赋值函数,用来给某一块内存空间进行赋值的: 包含在头文件中,可以用它对一片内存空间逐字节进行初始化: 原型为 : void *memset(void *s, int v, si ...

  9. c语言中快排函数,c语言快排函数详解

    c语言快排函数详解 int cmp(const void *a, const void *b) 返回正数就是说 cmp 传入参数第一个要放在第二个后面, 负数就是传入参数第一个要放第二个前面, 如果是 ...

  10. gets和fgets函数及其区别,C语言gets和fgets函数详解

    gets和fgets函数及其区别,C语言gets和fgets函数详解 每当讨论 gets 函数时,大家不由自主地就会想起 1988 年的"互联网蠕虫",它在 UNIX 操作系统的 ...

最新文章

  1. 什么场景使用mysql的存储过程_mysql存储过程的使用
  2. UIButton文字居左显示
  3. 如何将机器学习模型的正确率从 80%提高到 90%以上
  4. Windows Server 2003 网络互访新特性
  5. android仿微博头像_Android 仿instagram和微博的头像点击加载动画
  6. 内向的人很难成为群体程序员吗?
  7. jzoj4252-QYQ的图【dfs】
  8. 用Anaconda3搭建自己的TensorFlow环境
  9. 基本数据结构之Sort
  10. 001 - CMake 安装
  11. 微型计算机原理及应用吴宁课后答案,微机原理及应用(吴宁) 习题答案chapter7(4页)-原创力文档...
  12. 国资入局,苏宁“零售服务商”升级战略获得最强助力
  13. ITIL 2011服务管理与认证读书笔记一——IT服务管理与ITIL
  14. 动态数码管显示(proteus仿真图和程序)
  15. win7共享20人限制 清除_中控智慧考勤门禁_机器直连软件及清除管理员
  16. mysql调查问卷数据库设计_客服-问卷调查-问题答案表 - 数据库设计 - 数据库表结构 - 果创云...
  17. yolov5 数据集预处理(多文件夹同时提取文件并分类)(同时随机提取一定比例的图片和txt文件到指定文件)
  18. NetBIOS编程获取本机MAC地址及一个小坑
  19. 苹果登录skype显示无法连接服务器,无法连接appstore服务器 无法连接appstore服务器怎么办呢...
  20. RSA结合DES解决上下行接口的安全性问题

热门文章

  1. 【JavaWeb学习】HTML的基础标签
  2. 2、深入HTTP请求流程
  3. 人工智能的嘴巴——语音合成(Text to Speech | TTS)
  4. ant vue 的datepicker类组件中英文混合显示解决
  5. mysql删除多表视图数据,【杂谈】怎样删除mysql数据表视图中数据
  6. C# 判断本机是否安装Excel及多版本安装?获取Excel进程信息和打开Excel应用软件
  7. daphile的dsd设置_小块头有大能量 篇二:JaguarBoard之Daphile HiFi 畅享
  8. Spirng的事务 方法A调用方法B,事务是否失效
  9. Maven项目依赖管理 学习笔记
  10. 开发基于 Google Map 的 Android 应用