96SEO 2026-02-23 11:21 7
什么是函数库函数自定义函数函数执行示例函数的参数函数的调用函数的嵌套调用和链式访问函数的定义和声明

数学中我们常见到函数的概念。
但是你了解C语言中的函数吗C语言中的函数可不是数学上的表达式咱一起来看看它究竟是什么(︶)↗[GO!]
我们知道原材料进入工厂后之后就会有产品产出。
函数就像是工厂一样我们将没有处理过的数据放进去它就会返回给我需要的结果。
在维基百科中将函数解释为子程序。
因为函数具有独立处理数据或实现一部分功能的能力。
下面我们来看一下比较官方的解释
由一个或多个语句块组成。
它负责完成某项特定任务而且相较于其他代码具备相对的独立性。
一般会有输入参数并有返回值提供对过程的封装和细节的隐藏。
这些代码通常被集成为软件库。
在C语言中函数分为自定义函数和库函数。
自定义函数就是程序员需要自行实现的函数而库函数是C语言库中自带的我们可以在包含对应头文件的情况下使用。
World。
这时我们调用了printf函数并且是在包含了stdio头文件的前提下。
其实printf已经在stdio头文件编写好了我们需要时可以随时调用。
我们先来介绍一些常用的库函数吧。
首先看看pow函数它用于计算n的k次方第一个传入的参数是底数第二个传入的参数是指数。
例如计算
}再来介绍一个求字符串长度的函数strlen只要将字符串传入它就会将字符串长度返回。
string.h//调用strlen函数需要包含string头文件int
}最后我们介绍一下字符串拷贝函数strcpy。
如果我们要将str1中的字符拷贝到str2中则可以使用strcpy(str2,
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;strcpy(str2,
}★ps字符串在存储时最后一个位置会以\0结束表示字符串结束。
strcpy在拷贝时会将被拷贝字符串的\0字符一并拷贝下来。
现在我们就能知道为什么要有库函数了。
像上面我们描述的基础功能它们不是业务性的代码。
我们在开发的过程中每个程序员都可能用的到为了支持可移植性和提高程序的效率所以C语言的基础库中提供了一系列类似的库函数方便程序员进行软件开发。
当然C语言中有那么多的库函数我们不可能记得牢固在需要的时候我们可以上官方文档查询→C语言库函数查询通道
如果库函数能干所有的事情那还要程序员干什么所有更加重要的是自定义函数。
但是不一样的是这些都是我们自己来设计。
这给程序员一个很大的发挥空间。
下面我们看一看函数的组成↓↓↓
我们先看一个例子吧下面代码的get_max用于获取两个数中的较大值↓↓↓
}看完这段代码可能还是不大理解它的执行流程。
下面我通过图片文字解释的方式模拟程序执行流程。
程序从main函数依次向下执行如图所示执行1、2、3号语句。
当执行到printf函数所在行时因为调用了get_max函数此时程序跳转到get_max代码所在位置执行执行完毕后将计算结果返回给调用位置。
此时printf再打印出最大值。
在上面的代码中我们看到printf中的get_max()中有两个参数分别是m和n。
而main函数上方的get_max函数中也有两个参数即num1和num2。
下面我们来聊聊这两个地方的参数有什么不同再聊聊程序调用函数时内存的变化。
★ps程序在执行过程中会将函数信息、变量等保存在栈中。
栈保存数据从高地址向低地址处保存。
栈有后进先出的特点后放进去的数据要先取出来才能取其他数据。
①函数执行到main函数时会将main函数信息入栈入栈就是保存到栈空间的意思如下图所示。
②执行m和n的定义语句后会先后在栈中开辟一个空间用于保存m和n的数值。
③执行scanf语句读取用户输入保存到m和n所在地址。
这里假设输入的数值是8和5。
④执行printf时遇到了get_max函数此时调用get_max函数则需要将该函数的信息先入栈。
将m的值传递给num1时此时num1入栈并初始化为8将n的值传递给num2时此时num2入栈并初始化为5。
⑤在get_max函数执行完毕后num2、num1、get_max依次出栈出栈就是从栈空间删除的意思。
在整个程序执行完毕n、m、main函数依次出栈。
这里的m和n是实参它们是在函数调用前已经存在的变量。
而num1、num2称为形参它们是在函数调用时才开辟空间的变量。
下面看一下实参和形参的具体定义
真实传给函数的参数叫实参。
实参可以是常量、变量、表达式、函数等。
无论实参是何种类
型的量在进行函数调用时它们都必须有确定的值以便把这些值传送给形参。
形式参数是指函数名后括号中的变量因为形式参数只有在函数被调用的过程中才实例化分配
内存单元所以叫形式参数。
形式参数当函数调用完成之后就自动销毁了。
因此形式参数只在
现在我有个想法我想实现一个交换两个数数值的函数你来判断一下下面的代码能否实现交换两个数值的效果。
}这段代码无法实现m和n的数值交换。
因为m和n传递给num1和num2时num1和num2开辟了新的空间num1和num2的交换并不会影响m和n。
两者存放的位置都不一样不会互相影响的。
如果我们真的想实现两个数的数值交换则调用函数时函数中交换的必须是主函数中的m和n而不能再另外开辟空间。
咱们来看一下新的代码↓↓↓
}这段代码在调用函数时将m和n的地址传递给get_max函数get_max函数中使用指针进行接收。
在m和n存储位置上的交换操作就能真正交换m和n的数值了。
传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
这种传参方式可以让函数和函数外边的变量建立起正真的联系也就是函数内部可以直接操作函数外部的变量。
year);if(is_leap_year(year))printf(是闰年\n);elseprintf(不是闰年\n);return
}★ps闰年满足如下条件中的一个①能被4整除且不能被100整除②能被400整除。
嵌套调用是指一个函数中调用了另一个函数。
我们来看一个例子你就会知道了↓↓↓
{printf(starting....\n);sayHi();
}上面代码中introduc函数中被调用后它又调用了sayHi函数。
像这种在一个函数中调用另一个函数的情况就称为函数的嵌套调用。
“,43)的返回值作为下一个printf函数的参数的情况称为链式调用。
这里用图片解释一下这个代码的执行过程↓↓↓
最后有一个空格一共3个字符所以它的返回值为3。
在执行绿色框的printf时它打印3
一共2个字符所以它的返回值为2。
在执行最外围的printf时它打印2
首先让我们谈一谈函数的定义函数的定义就是给出函数的名称、参数、返回值并且给出函数体给出函数的具体实现。
下面给出函数定义的具体描述
例如下面的Add函数就是函数定义因为它给出了Add函数具体是怎么实现的。
}上面给出的各个例子中我都会将自定义函数放在main函数之前。
因为编译器在处理代码时是从上到下的。
假如我们将自定义函数放在main函数的后面若此时main函数中调用了自定义函数编译器此时并不认识因为它还没读到此时编译器将会报错。
下图中蓝色部分是编译器已经读到的部分因为get_max函数编译器还没读到当读到调用get_max函数时就会报错。
为了避免编译器报错我们可以在main函数前给出函数的声明即使函数定义在main函数后也不用担心了。
告诉编译器有一个函数叫什么参数是什么返回类型是什么。
但是具体是不是存在无关
紧要。
函数的声明一般出现在函数的使用之前。
要满足先声明后使用。
函数的声明一般要放在头文件中的。
关于上面的第3条我来解释解释吧。
在实际开发过程中一个项目需要很多程序员开发大家不可能同时在一个源文件中编写代码。
此时我们可以先在后缀为.h的头文件中给出各个函数的声明在函数的定义的文件中包含这个头文件在调用这些函数的主函数所在文件也包含这个头文件就可以了。
★ps包含C语言库的头文件使用#include头文件名.h调用自定义的头文件使用#include
下面就是一个分文件编写的示例。
max.h中保存的是函数的声明mac.c保存的是函数的定义。
在编译器读取前main.c时#include
max.h语句会将max.h中的函数声明文本替换到main.c中当执行到get_max时编译器会自动跳转到max.c中指定对应的函数。
一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算大大地减少了程序的代码量。
存在限制条件当满足这个限制条件的时候递归便不再继续。
每次递归调用之后越来越接近这个限制条件。
上面我们介绍了函数调用会将函数的相关信息保存到栈中如果无限递归则栈会被装满此时就会报错。
上面这堆关于递归的解释还是让人头大下面给些例子图形解释来理解一下函数递归吧。
}以n4为例我们来看一下函数递归的执行过程。
main函数指定到printf时调用了cal(4)。
下面给出cal(4)的执行步骤
⑧cal(4)的return语句返回cal(3)4即返回64给调用处
下面再出一个递归示例接收一个整型数打印它的每一位。
例如123打印1
①调用printNum(123)。
printNum(123)执行if语句判断条件成立调用printNum(123
②printNum(12)执行if语句判断条件成立调用printNum(12
③printNum(1)执行if语句判断条件不成立打印1后返回
经过上面的介绍对函数递归有了大致的了解了在介绍函数调用时我们讲到了函数调用时需要保存函数的信息也称为建立栈帧。
如果递归的层数过多则时空效率过低。
下面我们通过一个例子来讲解递归存在的问题同时比较一下迭代相比递归的优势。
下面是一个以递归形式实现的求解斐波那契数列的代码↓↓↓
}以fib(50)为例它的执行过程如下所示。
我们可以发现fib(46)等被多次计算这导致了大量的时间和空间的浪费。
我们可以通过执行下面代码得出在计算fib(50)时重复计算fib(3)多少次这将会是一个很大的数字。
系统分配给程序的栈空间是有限的但是如果出现了死循环或者死递归这样有可能导致一直开辟栈空间最终产生栈空间耗尽的情况这样的现象我们称为栈溢出。
将递归改写成非递归。
使用static对象替代nonstatic局部对象。
在递归函数设计中可以使用static对象替代nonstatic局部对象即栈对象这不仅可以减少每次递归调用和返回时产生和释放nonstatic对象的开销而且static对象还可以保存递归调用的中间状态并且可为各个调用层所访问。
}相比于递归的重复计算迭代法并不会出现。
将两份代码放Visual
许多问题是以递归的形式进行解释的这只是因为它比非递归的形式更为清晰。
但是这些问题的迭代实现往往比递归实现效率更高虽然代码的可读性稍微差些。
当一个问题相当复杂难以用迭代实现时此时递归实现的简洁性便可以补偿它所带来的运行时开销。
小明每次可以向上爬一阶或者两阶楼梯现输入台阶的阶数请输入爬到楼顶的方法数。
例如3阶台阶的方法数为34阶台阶的方法数为5。
}爬到第n阶台阶可以是从n-1号台阶爬1阶到达也可以是从n-2号台阶爬2阶到达。
由此可以到climb(n)
2)。
这道题是一个递归可实现的问题也可以用动态规划的方法迭代的方式实现哦
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback