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

15-C语言:第15~16天笔记

函数指针

定义

函数指针本质上是指针,是一个指向函数的指针。函数都有一个入口地址,所谓指向函数

的指针,就是指向函数的入口地址。(这里的函数名就代表入口地址)

函数指针存在的意义:

  • 让函数多了一种调用方式
  • 函数指针可以作为形参,可以形式调用(回调函数)

遵循:先有函数,后有指针

语法:

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

举例:

int (*fun)(int a, int b);int (*fun)(int, int); // 有点类似于函数声明

函数指针的初始化

① 定义的同时赋值

// 函数指针需要依赖于函数,先有函数,后有指针
// 定义一个普通函数
int add(int a, int b) { return a + b; }
// 定义一个函数指针,并初始化
// 观察:函数指针的返回类型和指向的函数的返回类型一致,函数指针的形参个数、类
型、位置和指向的函数的参数的一致。
int (*p)(int a, int b) = add; // 函数指针p指向函数add,这里的add不能带(),
add就表示函数的入口地址

② 先定义,后赋值

// 定义一个普通函数int add(int a, int b) { return a + b; }int (*p)(int, int); // 形参列表的参数名可以省略不写p = add; // 此时是将add的入口地址赋值给指针p

注意:

  1. 函数指针指向的函数要和函数指针定义的返回值类型,形参列表对应,否则编

译报错

  1. 函数指针是指针,但不能指针运算,如p++等,没有实际意义
  2. 函数指针作为形参,可以形成回调
  3. 函数指针作为形参,函数调用时的实参只能是与之对应的函数名,不能带小括

号()

  1. 函数指针的形参列表中的变量名可以省略

注意:函数不能作为函数的形参,但是指向函数的函数指针是可以作为函数的形参的。

案例

需求:求a,b两个数的最大值

代码:

#include <stdio.h>/**\* 定义一个函数,求两个数的最大值*/int get_max(int a, int b){return a > b ? a : b;}int main(int argc,char *argv[]){// 定义测试数据int a = 3, b = 4, max;// 直接调用函数max = get_max(a, b);printf("%d,%d中的最大值是:%d\n",a,b,max);// 定义一个函数指针int (*p)(int, int) = get_max;// 间接调用函数:方式1max = p(a,b);printf("%d,%d中的最大值是:%d\n",a,b,max);// 间接调用函数:方式2max = (*p)(a,b); // () > [] > *printf("%d,%d中的最大值是:%d\n",a,b,max);return 0;
}

回调函数

定义

	==回调函数就是一个通过函数指针调用的函数==。如果你把函数的指针作为参数传递给另

一个函数,当这个指针被用来调用其所指向的函数时。我们就说这是回调函数。回调函数

不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,

用于对该事件或条件进行响应。

​ 简单来说,就是使用函数指针作为函数的形参,这种函数就被称作回调函数。

为什么要用回调函数

​ 因为可以把调用者与被调用者分开,所以调用者不关心谁是被调用者。它只需知道存

在一个具有特定原型和限制条件的被调用函数。

​ 简而言之,回调函数就是允许用户把需要调用的方法的指针作为参数传递给一个函

数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。

案例

#include <stdio.h>
/**
\* 回调函数1*/int callback_1(int a){printf("hello, this is callback_1:a=%d\n", a);return a;}/**\* 回调函数2*/int callback_2(int b){printf("hello, this is callback_2:b=%d\n", b);return b;}/**\* 回调函数3*/int callback_3(int c){printf("hello, this is callback_3:c=%d\n", c);return c;}/**\* 实现回调函数(形参是函数指针的函数)*/int handle(int x, int (*callback)(int)){printf("日志:开始执行任务!\n");int res = callback(x);printf("日志:执行结果:%d\n",res);printf("日志:结束执行任务!\n");}int main(int argc,char *argv[]){handle(100,callback_1);handle(200,callback_2);handle(300,callback_3);return 0;}

运行结果:

在这里插入图片描述

二级指针

定义

​ 二级指针(多重指针)用于储存一级指针的地址,需要两次解引用才能访问原始数据。其

他多重指针的用法类似,但实际开发中最常见的指针是二级指针。

int a = 10; // a是普通变量,也就是原始数据
int *p = &a; // 一级指针,p指向a,解引用1次就可以获取a的值
printf("%d\n", *p); // 10int **w = &p; // 二级指针,w指向p,解引用2次就可以获取a的值
printf("%d\n", **w);// 10int ***k = &w; // 三级指针,k指向w,解引用3次就可以获取a的值
printf("%d\n", ***k); // 10 int a1 = ***k; int *a2 = **k; int **a3
= *k; int ***a4 = k;
语法

数据类型 **指针变量名 = 指针数组的数组名 | 一级指针的地址

特点

与指针数组的等效性 二级指针与指针数组在某些时候存在等效性,但与二维数组不等

效。二维数组名是数组指针类型,如 int (*)[3] ,而非二级指针。

// 指针数组
int arr[] = {11,22,33};
int *arr_[] = {&arr[0],&arr[1],&arr[2]};
// 二级指针接收指针数组
char *str[3] = {"abc","aaa034","12a12"};
char **p = str; // p:数组首地址,行地址,默认0行 *p:列地址,默认0行0列
**p:列元素
#include <stdio.h>
int main(int argc,char *argv[])
{char *str[3] = {"abc","aaa034","12a12"};char **p = str;// 打印字符串// for (int i = 0; i < 3; i++)// {// printf("%s\n", *p);// p++;// }// 打印字符int i = 0;while(**p != '\0'){printf("%-2c",**p);(*p)++;}printf("\n");return 0;
}

与二维数组的差异 二维数组名是数组指针类型,直接赋值给二级指针会导致类型不匹

// 数组指针可以指向一个二维数组
int arr[2][3] = {{1,3,5},{11,33,55}};
int (*p)[3] = arr;
// 二级指针不等效二维数组
int **k = arr; // 编译报错 arr类型 int(*)[3] 不兼容 k类型 int**

0’)
{
printf(“%-2c”,**p);
(*p)++;
}
printf(“\n”);
return 0;
}


② **与二维数组的差异** 二维数组名是数组指针类型,直接赋值给二级指针会导致类型不匹配

// 数组指针可以指向一个二维数组
int arr[2][3] = {{1,3,5},{11,33,55}};
int (p)[3] = arr;
// 二级指针不等效二维数组
int **k = arr; // 编译报错 arr类型 int(
)[3] 不兼容 k类型 int**

http://www.xdnf.cn/news/16526.html

相关文章:

  • JSON解析
  • 力扣刷题(第一百零二天)
  • BitMart 启动中文品牌“币市”:引领加密资产本地化发展新篇章
  • 闪测影像测量软件见证工业美学中的精密制造-VisionX轮廓度评价
  • Node.js 内置模块
  • 【Mac版】Linux 入门命令行快捷键+联想记忆
  • Qt 移动应用界面设计原则
  • 2025北京师范大学数学分析考研试题
  • Java把word转HTML格式
  • 《从HTTP到IP证书:网络身份验证的下一站革命》
  • 偏二甲肼气体浓度报警控制系统
  • Transformer实战——BERT模型详解与实现
  • <RT1176系列12>DMAMUX入门级应用和DMAMUX MAP表
  • STM32项目分享:智能厨房安全系统(机智云)
  • day064-kodbox接入对象存储与配置负载均衡
  • 并发安全之锁机制一
  • LLM Landscape:2025年大语言模型概览
  • 电子电路原理学习笔记---第4章二极管电路---第3天
  • Python全栈项目--基于深度学习的视频内容分析系统
  • Python与Mysql
  • C++算法实例精讲
  • 分布式微服务--核心组件与架构关系(一)
  • 深度研究——OpenAI Researcher Agent(使用OpenAI Agents SDK)
  • Mac查看本机ip地址
  • Leetcode_242.有效的字母异位词
  • Windows 11 下 Anaconda 命令修复指南及常见问题解决
  • linux du、df命令使用教程
  • node后端-JWT认证
  • Java面试宝典:MySQL事务和事务的隔离级别
  • 《中国棒球》cba球队有哪些球队·棒球1号位