函数指针史上最全的介绍

函数指针

一. 函数指针的概念

如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。而且函数名表示的就是这个地址。既然是地址我们就可以定义一个指针变量来存放,这个指针变量就叫作函数指针变量,简称函数指针。

函数指针的定义方式可以如下表示:

函数返回值类型 (* 指针变量名) (函数参数列表);int(*p)(int, int);那么这个指针 p 就可以指向形如:int add(int a, int b);int get_info(int board, int module);
这样类型的指针,形如:p = add;p = get_info;

我们进行对函数指针进行初始化的时候可以做如下操作:

  1. 首先定义一个指针变量。

  2. 将同类型的函数名赋值给它。

/* 定义函数 */
int add(int a, int b)
{return a + b;
}int main()
{// 方法一, 先定义再赋值int (*p1)(int, int);p1 = add;DH_INFO("%d\n", p1(3, 7));// 方法二, 同时定义赋值int (*p2)(int, int) = add;DH_INFO("%d\n", p2(3, 7));   
}

使用typedef定义函数指针

在工程上,为了提高开发效率和代码可读性的问题,通常会用typedef对函数指针进行转定义

typdef 函数返回值类型 (*指针类型名) (函数参数列表);typedef uint32_t (*xxx_callback)(int cb_type);此时,通过typedef转定义的为指针类型名,相当于数据结构,(从面相对象的角度来看可以称为类)
可以用于新建(实例化一系列函数指针变量),形如:xxx_callback init_callback;xxx_callback move_callback;而此时根据实际不同业务模块处理的不同,可以将实例化的函数指针变量赋值为不同模块的函数。定义 uint32_t service_init_cb(int cb_type) { return 0; }赋值 init_callback = service_init_cb;使用 ret = init_callback(0);/* 实际代码 */
typedef uint32_t (*xxx_callback)(int cb_type);uint32_t service_init_cb(int cb_type)
{ return cb_type;
}int main()
{/* 实例化函数指针 */xxx_callback init_callback;service_init_cb(3);init_callback = service_init_cb;init_callback(5);
}

函数指针作为函数入参

在工程上,函数指针作为入参,通常用于函数回调。

int add(int a, int b)
{return a + b;
}int sub(int a, int b)
{return a - b;
}int get_result(int a, int b, int (*math_cal)(int, int))
{return math_cal(a, b);
}int main()
{int res1, res2;res1 = get_result(3, 2, add);res2 = get_result(3, 2, sub);printf("add_res = %d, sub_res = %d\n", res1, res2);
}

存放函数指针的数组

函数返回值类型 (* 指针变量名[数组长度]) (函数参数列表);int (*math_cal[2])(int, int);
math_cal[0] = add;
math_cal[1] = sub;
for (int i = 0; i < 2; i++) {printf("Math cal %d res = %d\n", i, math_cal[i](3, 2));
}动态申请( 还没有研究,求指导)使用typedef的模式: 定义函数指针数据类,利用该数据类常规实例化一个函数数组。
typedef uint32_t (*xxx_callback)();
xxx_callback g_cb_list[10];
int g_len;
uint32_t xxx_callback_register(xxx_callback callback)
{if(!callback) {printf("call back not exist");return -1;}g_cb_list[g_len++] = callback;return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言调试技巧:stdin,stdout,stderr

stdin,stdout,stderr流 介绍 stdin&#xff0c;stdout&#xff0c;stderr是标准的输入输出流。其中&#xff0c;stdin是访问键盘输入&#xff0c;stdout和stderr分别是向终端输出数据。 关键函数 fscanf/fprintf /* 所在头文件 */ #include <stdio.h>int fscanf(FILE…

C语言调试技巧:main函数输入参数

带入参的main函数 介绍 带入参的main函数主要用于一些基本调试&#xff0c;main函数的入参在main函数里被解析为字符串&#xff0c;因此根据具体的调试业务可以需要将字符串转为相应的int类型或double类型进行其他的操作。 函数实现 // test_mainin.c #include <stdio.h…

[Leetcode456]132模式 - 单调栈

[Leetcode456]132模式 - 单调栈 给你一个整数数组 nums &#xff0c;数组中共有 n 个整数。132 模式的子序列 由三个整数 nums[i]、nums[j] 和 nums[k] 组成&#xff0c;并同时满足&#xff1a;i < j < k 和 nums[i] < nums[k] < nums[j] 。 暴力遍历&#xff0c;…

[Deepin - Pycharm] PyQT5安装配置

[Deepin - Pycharm] PyQT5安装配置 1.环境依赖 python3基础环境&#xff0c; pip下载器 pycharm编辑器 2. 从系统环境中安装pyqt5, qtdesigner >>> pip install pyqt5 >>> sudo apt-get install pyqt5* >>> sudo apt-get install qt5-default …

[Deepin - Pycharm调试记录] Pyinstaller索引系统库问题

Deepin - Pycharm调试记录 - Pyinstaller索引不到系统库 现象 在Pycharm的Terminal中执行Pyinstaller指令时候遇到如下报错提示 OSError: Python library not found: libpython3.7mu.so.1.0, libpython3.7.so.1.0, libpython3.7.so, libpython3.7m.so.1.0, libpython3.7m.so…

Python学习笔记(5):Python如何忽略warning的输出

告警现象 形如下图文的告警信息都可以使用告警屏蔽 添加代码 源代码添加 import warnings warnings.filterwarnings("ignore")命令行执行 python -W ignore file.py可以避免warnings输出影响我们调试&#xff0c;但是不要盲目设置取消输出。因为告警内容可能包…

[Deepin - Pycharm调试记录] Matplot3D动态画图报错问题

Deepin - Pycharm调试记录 - Matplot3D动态画图报错问题 写在开头的话 应该不会有人傻到看这个wiki吧&#xff0c;我花了1个小时才发现问题&#xff0c;是我自己方法调错了。 这个wiki不会细致的教大家如何使用matplotlib进行动态画图&#xff0c;或者动态画图的几种办法&…

【C语言基础】C语言异常捕获机制 - setjmp

C语言异常捕获机制 - setjmp 快速入门 想快速入门该模块请访问&#xff1a;介绍&#xff0c;数据接口&#xff0c;示例代码 介绍 C语言没有C或Java的异常捕获机制&#xff0c;但可以通过setjmp/longjmp实现类似的效果&#xff1a; 使用setjmp保存当前执行环境到jmp_buf&am…

【C语言基础】C语言异常捕获机制 - assert

C语言异常捕获机制 - assert 快速入门 想快速入门该模块请访问&#xff1a;介绍&#xff0c;数据接口&#xff0c;示例代码 介绍 通常一个良好的代码功能运行环境都有功能运行前检查和运行后检查两个方面。&#xff23;语言中提供了assert机制来做这件事情 assert 的作用是…

【c语言数据结构】二叉树

c语言数据结构完全二叉树 快速开始 直接参考示例代码即可 介绍 概念 二叉树&#xff08;Binary tree&#xff09;是树形结构的一个重要类型。 许多实际问题抽象出来的数据结构往往是二叉树形式&#xff0c;即使是一般的树也能简单地转换为二叉树&#xff0c; 二叉树的存…

git 指令全集

git 指令全集 指令集参考这里&#xff0c;后续会继续整理 https://www.runoob.com/git/git-tutorial.html 基本使用流程 场景&#xff11;&#xff1a;建立新仓 首先在本地新建一个仓 ~$ mkdir git_workspace ~$ git init与远程仓建立连接 # 查看所有的远端分支 -$ git rem…

UTHash使用教程

UTHash使用教程 快速入门 想快速入门该模块请访问&#xff1a;介绍&#xff0c;数据接口&#xff0c;示例代码 介绍 Hash &#xff1a;散列&#xff0c;通过关于键值(key)的函数&#xff0c;将数据映射到内存存储中一个位置来访问。这个过程叫做Hash&#xff0c;这个映射函…

【C语言基础】gdb调试工具的使用

gdb调试教程 快速入门 要想快速入门gdb调试&#xff0c;可以直接翻阅基本案例&#xff1a;采内存 介绍 GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。 对于一名Linux下工作的c/c程序员&#xff0c;gdb是必不可少的工具 …

C/C++队列与循环队列

C/C数据结构 - 队列 循环队列 快速入门 介绍 1. 队列的定义 队列是一种线性存储结构&#xff0c;每次对队列的增删操作如下 增&#xff1a;在队列尾部添加元素 删&#xff08;取出&#xff09;&#xff1a;在队列头部删除元素 这种数据存储方式遵循“先进先出”&#xff0…

PyQt特殊对话框介绍

PyQt特殊对话框 对话框基类&#xff1a;QDialog 对话框基本用法&#xff1a; 模态窗口&#xff1a; 当窗口设置为模态窗口时&#xff0c;不能对其父级别的窗口进行操作。QTdesigner里有控件可以勾选Func: QtWidgets.Dialog.setModal(True) [ True | False ] 窗口执行 exec&am…

PyQt5 让窗口在桌面居中的办法

屏幕居中核心函数 在我们开发的UI类中定义一个center方法&#xff0c;&#xff08;方法名自定&#xff0c;内容如下&#xff09;。其中QDesktopWideget方法在Qtwidgets头文件中。 然后在 __init__()中调用该 self.center()方法即可。 # 屏幕居中def center(self):# 获取窗口大…

PyQt5 QLineEdit输入密码

单行编辑器 QLineEdit 输入密码 单行编辑器直接继承于QWidget 常用方法&#xff1a; 设置显示模式&#xff1a;在设置密码栏常会使用这种模式 方法QLineEdit.setEchoMode 用法 假设你有一个QLineEdit()组件 self.UserpswdEdit QLineEdit()则你可以使用下面三种方式定义输…

Arduino 软件开发(一): GPIO读写

Arduino 软件开发&#xff08;一&#xff09; 目录 核心运行函数&#xff0c; 基础语法&#xff0c;数字控制&#xff0c;模拟控制 核心运行函数 void setup() 当Arduino程序开始运行时会调用setup()函数。通常setup()函数完成初始化一些变量、配置引脚状态及初始化调用的库…

JavaScript学习笔记:类与导包实例

NodeJS类与导包 在工程上&#xff0c;一个文件就是一个独立的模块&#xff0c;仅包含一个类。我们可以称之为类文件。因此当我们要使用这个模块的时候&#xff0c;我们会将这个类文件作为一个包导入到调用的文件里。方法如下&#xff1a; 0. 目录结构如下 - src|__ main.js|…

JavaScript学习笔记:常量,枚举,宏定义

NodeJS常量&#xff08;fake&#xff1a;宏定义&#xff09; 因为之前C/C代码开发习惯了&#xff0c;会用到一些宏定义来替换一些表意不明的数字&#xff08;就是含义不清的数字&#xff09;。而JS没有这种宏定义。上网找到一个链接作为参考&#xff1a;https://www.itranslat…