当前位置: 首页 > news >正文

特殊函数

> C语言三大特殊函数:静态函数(缩小可见域)、递归函数(自我调用)、回调函数(钩子/函数指针)。


一、静态函数:文件级私有化

  • 背景知识: 普通函数都是跨文件可见的,即在文件 a.c 中定义的函数可以在 b.c 中使用。
  • 静态函数: 只能在定义的文件内可见的函数,称为静态函数。
对比项 普通函数 静态函数
可见域 跨文件(全局符号) 本文件内(local符号)
重名冲突 容易 不易
链接阶段 外部可引用 外部不可见

语法

staitc void f(void) // 在函数头前面增加关键字 static ,使之成为静态函数
{// 函数体
}

要点:

  • 静态函数主要是为了缩小函数的可见范围,减少与其他文件中重名函数冲突的概率。
  • 静态函数一般被定义在头文件中,然后被各个源文件包含。

二、递归函数:自己调用自己

概念: 如果一个函数内部,包含了对自身的调用,则该函数称为递归函数

  • 递归问题:
    • 阶乘。
    • 幂运算。
    • 字符串翻转。
    • 二叉树的操作

要点:

  • 只有能被表达为递归的问题,才能用递归函数解决。
  • 递归函数必须有一个可直接退出的条件,否则会进入无限递归
  • 递归函数包含两个过程,一个逐渐递进的过程,和一个逐渐回归的过程。

示例1: 依次输出 n 个自然数。

  • 思路:先输出前面的 n-1 个自然数,再输出最后一个自然数n。而要输出前面的 n-1 个自然数,递归调用自身即可。
// 该函数的功能:依次输出 n 个自然数
void f(int n) 
{if(n < 0)          // 1,当满足此条件时,不再进行递归。return;f(n-1);            // 2,递归调用自己,输出前 n-1 个数printf("%d\n", n); // 3,输出最后一个自然数 n
}

递归调用时,函数的栈内存的变化如下图所示。可见,随着递归函数的层层深入,栈空间逐渐往下增长,如果递归的层次太深,很容易把栈内存耗光

  • 层层递进时,问题的规模会随之减小,减小到可直接退出的条件时,函数开始层层回归。
栈内存调用图

示例2: 字符串原地翻转

  • 思路: 先递归到尾,回归时交换首尾字符。
void reverse_r(char *left, char *right)
{if (left >= right) return;          // 终止char tmp = *left;*left  = *right;*right = tmp;reverse_r(left + 1, right - 1);     // 子问题
}int main(void)
{char s[] = "abcdefg";reverse_r(s, s + strlen(s) - 1);puts(s);    // gfedcbareturn 0;
}

栈深度 = strlen(s)/2,O(n) 时间 · O(n) 额外栈空间(嵌入式栈紧张时慎用)

三、回调函数(钩子函数)

概念: 函数实现方不调用该函数,而由函数接口提供方间接调用的函数,称为回调函数。

  • 示例: 系统中的信号处理,是一个典型的利用回调函数的情形。
示例图

要点:

  • 示例中函数 sighandler 是回调函数。
  • signal() 将函数回调函数传递给内核,使得内核可以在恰当的时机回调 sighandler
  • 应用开发者和内核开发者只要约定好回调函数的接口,即可各自开发,进度互不影响。

用例分析:

#include <signal.h>typedef void (*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t handler);signum --> 信号值handler  --> 信号的相应函数(处理函数)

以上函数的作用是,向系统注册一个信号响应函数,让系统知道如果本进程收到了signum信号时直接帮我调用 handler指向的函数!!

猪脚亮

如果一个函数 A,被作为参数传入了函数 B,并且函数 B 在执行过程中又回过来调用了函数 A,那么这个函数 A 就是一个回调函数。

http://www.gsyq.cn/news/21729.html

相关文章:

  • 一行代码也能行?极简实现GPIO按键关机(支持短按/长按)
  • 抖音麒麟福袋软件操作指南
  • 平面图最小割与对偶图最短路 - 干
  • 2025 苏州注册公司服务机构实用推荐:选择深度解析
  • LeetCode | 45. 跳跃游戏 II(转载)
  • 实用指南:mysql_query函数:数据库世界的信使
  • 基于MATLAB的车道线检测
  • 断言
  • 2025 年国内小程序开发优质机构最新推荐排行榜:覆盖多领域需求,助力政企精准选型
  • Python 受保护成员和私有成员
  • 2025 单招综评培训机构推荐榜:济南易升教育 5 星领跑,适配基础/冲刺/面试全流程备考
  • 深入解析:Scikit-learn Python机器学习 - 聚类分析算法 - Agglomerative Clustering(凝聚层次聚类)
  • “一切皆文件”:揭秘LINUX I/O与虚拟内存的底层设计哲学
  • firewalld和iptables的区别与应用
  • 视觉定位引导劈刀修磨系统赋能芯片封装
  • @wraps(func)
  • 大素材毕业设计选题推荐-基于大数据的全球经济指标数据分析与可视化环境-Hadoop-Spark-数据可视化-BigData
  • 在 gitea 服务器端查询 lfs 文件占用情况
  • HDR图像生成算法详解
  • 基于MATLAB的二自由度机械臂PID控制仿真
  • Ventoy引导Kali live USB持久化
  • 【面试题】人工智能工程师高频面试题汇总:循环神经网络篇(题目+答案)
  • 做了个手机上的“视频播放器”,获益匪浅
  • CEF关闭流程
  • AI一周资讯 251005-251015
  • 075_尚硅谷_位运算深度讲解
  • iOS框架内存中占用很高的ttc文件是否正常
  • MPC模型预测控制:原理、设计与MATLAB实现
  • 美股 SaaS 巨头如何用 Karpenter 节省 1/4 的 EC2 成本
  • 题解:qoj7303 City United