C语言指针详解进阶2

函数指针数组

数组是一个存放相同类型数据的存储空间,那我们已经学习了指针数组,
比如:
int *arr[10];
//数组的每个元素是int

那要把函数的地址存到一个数组中,那这个数组就叫 函数指针数组 ,那函数指针的数组如何定义呢?
int (*parr1[10])();
int *parr2[10]();
int (*)() parr3[10];
答案是: parr1
parr1 先和 [] 结合,说明 parr1 是数组,数组的内容是什么呢?
int (*)() 类型的函数指针。
函数指针数组是一个数组,每个元素都是一个函数指针。函数指针指向函数的内存地址,可以用来动态地调用函数。通过定义一个函数指针数组,可以将多个不同的函数作为数组的元素,便于根据需要选择并调用特定的函数。
#include <stdio.h>// 定义几个简单的函数
int add(int a, int b) {return a + b;
}int subtract(int a, int b) {return a - b;
}int multiply(int a, int b) {return a * b;
}int main() {// 声明一个函数指针数组,大小为3int (*operation[3])(int, int);// 将函数的地址赋值给函数指针数组的元素operation[0] = add;operation[1] = subtract;operation[2] = multiply;// 使用函数指针调用特定的函数int result = operation[0](2, 3);printf("Result: %d\n", result);result = operation[1](5, 2);printf("Result: %d\n", result);result = operation[2](4, 6);printf("Result: %d\n", result);return 0;
}

函数指针数组的用途:转移表

例子:(计算器)

#include <stdio.h> int add(int a, int b) { return a + b; 
} 
int sub(int a, int b) { return a - b; } int mul(int a, int b) { return a*b; } int div(int a, int b) {return a / b; } int main() { int x, y; int input = 1; int ret = 0; do { printf( "*************************\n" ); printf( " 1:add 2:sub \n" ); printf( " 3:mul 4:div \n" ); printf( "*************************\n" ); printf( "请选择:" ); scanf( "%d", &input); switch (input) {
case 1: printf( "输入操作数:" ); scanf( "%d %d", &x, &y); ret = add(x, y);printf( "ret = %d\n", ret);break; case 2:printf( "输入操作数:" ); scanf( "%d %d", &x, &y); ret = sub(x, y);printf( "ret = %d\n", ret);break; case 3:printf( "输入操作数:" ); scanf( "%d %d", &x, &y); ret = mul(x, y);printf( "ret = %d\n", ret);break; case 4:printf( "输入操作数:" ); scanf( "%d %d", &x, &y); ret = div(x, y);printf( "ret = %d\n", ret);break; case 0:printf("退出程序\n"); breark;default:printf( "选择错误\n" ); break;} } while (input);return 0;}

使用函数指针数组的实现:

#include <stdio.h> 
int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; } int mul(int a, int b) { return a*b; } int div(int a, int b) { return a / b; } int main() {int x, y; int input = 1; int ret = 0; int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //转移表 while (input) {printf( "*************************\n" ); printf( " 1:add 2:sub \n" ); printf( " 3:mul 4:div \n" ); printf( "*************************\n" ); printf( "请选择:" ); scanf( "%d", &input); if ((input <= 4 && input >= 1)) {printf( "输入操作数:" );scanf( "%d %d", &x, &y);ret = (*p[input])(x, y); } elseprintf( "输入有误\n" );printf( "ret = %d\n", ret);} return 0;}

指向函数指针数组的指针

指向函数指针数组的指针是一个 指针

指针指向一个 数组 ,数组的元素都是 函数指针;

如何定义?

void test(const char* str) { printf("%s\n", str); } int main() { //函数指针pfun void (*pfun)(const char*) = test; //函数指针的数组pfunArr void (*pfunArr[5])(const char* str); pfunArr[0] = test; //指向函数指针数组pfunArr的指针ppfunArr void (*(*ppfunArr)[5])(const char*) = &pfunArr; return 0;}

回调函数

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数 的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

首先演示一下qsort函数的使用:

#include <stdio.h>//qosrt函数的使用者得实现一个比较函数 int int_cmp(const void * p1, const void * p2) { return (*( int *)p1 - *(int *) p2); }int main() {int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 }; int i = 0;qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp); for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++) { printf( "%d ", arr[i]); } printf("\n"); return 0;}

使用回调函数,模拟实现qsort(采用冒泡的方式)。

注意:这里第一次使用 void*的指针,讲解void*的作用。

#include <stdio.h>int int_cmp(const void * p1, const void * p2) { return (*( int *)p1 - *(int *) p2); }void _swap(void *p1, void * p2, int size) {int i = 0;for (i = 0; i< size; i++){char tmp = *((char *)p1 + i);*(( char *)p1 + i) = *((char *) p2 + i);*(( char *)p2 + i) = tmp;}}void bubble(void *base, int count , int size, int(*cmp )(void *, void *)) {int i = 0;int j = 0;
for (i = 0; i< count - 1; i++) {for (j = 0; j<count-i-1; j++){if (cmp ((char *) base + j*size , (char *)base + (j + 1)*size) > 0) { _swap(( char *)base + j*size, (char *)base + (j + 1)*size, size); }}}} int main() {int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };//char *arr[] = {"aaaa","dddd","cccc","bbbb"};int i = 0;bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++){printf( "%d ", arr[i]);} printf("\n"); return 0;}

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

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

相关文章

C++模拟揭秘刘谦魔术,领略数学的魅力

新的一年又开始了&#xff0c;大家新年好呀~。在这我想问大家一个问题&#xff0c;有没有同学看了联欢晚会上刘谦的魔术呢&#xff1f; 这个节目还挺有意思的&#xff0c;它最出彩的不是魔术本身&#xff0c;而是小尼老师“念错咒语”而导致他手里的排没有拼在一起&#xff0c;…

BUUCTF------[HCTF 2018]WarmUp

开局一个表情&#xff0c;源代码发现source.php <?phphighlight_file(__FILE__);class emmm{public static function checkFile(&$page){$whitelist ["source">"source.php","hint">"hint.php"];if (! isset($page) |…

06_netdev网卡设备内核模块

01_basicLinux内核模块-CSDN博客文章浏览阅读315次&#xff0c;点赞3次&#xff0c;收藏3次。环境IDubuntuMakefilemodules:clean:basic.creturn 0;运行效果。https://blog.csdn.net/m0_37132481/article/details/136157384my_netdev.c #include <linux/kernel.h> #incl…

基于springboot的大学生就业招聘系统的设计与实现论文

大学生就业招聘系统的设计与实现 摘要 随着信息互联网信息的飞速发展&#xff0c;大学生就业成为一个难题&#xff0c;好多公司都舍不得培养人才&#xff0c;只想要一专多能之人才&#xff0c;不愿是承担社会的责任&#xff0c;针对这个问题开发一个专门适应大学生就业招聘的网…

ChatGPT引领的AI面试攻略系列:cuda和tensorRT

系列文章目录 cuda和tensorRT&#xff08;本文&#xff09;AI全栈工程师 文章目录 系列文章目录一、前言二、面试题1. CUDA编程基础2. CUDA编程进阶3. 性能优化4. TensorRT基础5. TensorRT进阶6. 实际应用与案例分析7. 编程与代码实践8. 高级话题与趋势 一、前言 随着人工智能…

谈谈mysql 的日志?binlog 和 redo log 有什么区别?

谈谈mysql 的日志? MySQL数据库中有多种日志&#xff0c;其中最重要的是二进制日志&#xff08;binlog&#xff09;、重做日志&#xff08;redo log&#xff09;和回滚日志&#xff08;undo log&#xff09;。这些日志在数据库操作中起着至关重要的作用&#xff0c;不仅保证了…

大部分人只有在工作几年后才知道什么是程序员

在大学 大学时期的我们&#xff0c;有几个从大一就开始好好学习&#xff0c;立志考研的&#xff1f;大多数人都只是在“享受大学生活”&#xff0c;就连选择计算机专业都是别人推荐的&#xff0c;根本不知道将来毕业会干啥。在我们的印象中&#xff0c;程序员就是一个模糊的名…

QT----写完的程序打包为APK在自己的手机上运行

目录 1、qt安装android组件2、打开qt配置Android 环境3、手机打开开发者模式&#xff0c;打开usb调试&#xff0c;连接电脑4、运行代码 1、qt安装android组件 qtcreater–工具-QTMaintenaceTool-startMaintenaceTool—登陆—添加或修改组件—找到android&#xff0c;安装 若是…

深入探讨 AutoGPT:彻底改变游戏的自主 AI

原文地址&#xff1a;Deep Dive into AutoGPT: The Autonomous AI Revolutionizing the Game 2023 年 4 月 24 日 AutoGPT 是一个功能强大的工具&#xff0c;它通过 API 使用 GPT-4 和 GPT-3.5&#xff0c;通过将项目分解为子任务并在自动循环中使用互联网和其他工具来创建完…

C++Json项目笔记

Github源项目地址&#xff1a;TinyJson 本人仓库地址&#xff08;跟原版差别不大&#xff0c;只是在有疑惑或者有收获的地方加上的注释作为笔记&#xff09; 文章目录 类的提前声明为什么定义函数的时候同时写左值和右值作为传参&#xff1f;解答 SFINAE机制&#xff08;疑惑…

Python高光谱遥感数据处理与机器学习

通过高光谱矿物识别&#xff0c;木材含水量提取、土壤有机碳评估等案例&#xff0c;提供可借鉴的高光谱应用领域的技术服务方案&#xff0c;结合Python科学计算、可视化、数据处理与机器学习等开源开发库&#xff0c;深入介绍高光谱技术的应用功能开发。 高光谱遥感信息对于我…

C++11线程同步之条件变量

C11线程同步之条件变量 condition_variable成员函数生产者和消费者模型 condition_variable_any成员函数生产者和消费者模型 条件变量是C11提供的另外一种用于 等待的同步机制&#xff0c;它能阻塞一个或多个线程&#xff0c;直到收到另外一个线程发出的通知或者超时时&#x…

springboot+xjar加密打包部署教程

需求背景 为了跟上时代的步伐&#xff0c;为了更好的生存。开个玩笑&#xff0c;就是心血来潮&#xff0c;使用xjar加密部署jar包&#xff0c;于是就测试一下。 xjar教程 1-maven配置文件修改 首先找到自己ideal配置的maven文件夹&#xff0c;然后找到apache-maven-3.9.3\co…

vue修改打包后静态资源路径的修改

不得不说&#xff0c;ai是真的强大&#xff0c;直接自己生成。

消息队列-Kafka-基础架构

基础架构 官网地址 上面这张图类比RocketMQ 相当于对一个主题进行了分区&#xff08;类似于RockeMQ 消息队列&#xff09;&#xff0c;每个分区存储到不同的Broker。在发送消息的时候都是发送到主分区。如果一台Broker由于其它节点备份了挂掉节点的数据&#xff0c;所以可以…

世界的本质是旋转(6)-在复平面上借助软件无线电SDR解调BPSK波形

在上一篇文章中&#xff0c;已经完成了BPSK波形的发射。 相对于BPSK波形的生成总共就4行代码&#xff0c;接收要略微复杂一些&#xff0c;算上各种同步、锁相环&#xff0c;约80行。完整版参考Git仓库。 设备连接&#xff1a; #mermaid-svg-aMmvYQSgMzU6Gepf {font-family:&q…

探索Python编程世界:从入门到精通

一.Python 从入门到精通 随着计算机科学的发展&#xff0c;编程已经成为了一种必备的技能。而 Python 作为一种简单易学、功能强大的编程语言&#xff0c;越来越受到人们的喜爱。本文将为初学者介绍 Python 编程的基础知识&#xff0c;帮助他们踏入 Python 编程的大门&#xf…

Linux 驱动 中断(二)

中断下半部 在 Linux 内核中&#xff0c;中断下半部&#xff08;也称为中断下半场&#xff09;是指在中断服务程序&#xff08;Top Half&#xff09;执行完毕后&#xff0c;在上下文之外延迟执行的一些操作。中断下半部通常用于处理那些不适合在中断上下文中立即执行的任务&am…

O2OA(翱途)移动端如何查看系统日志?

O2OA(翱途)移动端如何查看系统日志&#xff1f; 一、进入APP移动端应用&#xff0c;点击右下角“设置” 二、点击“系统日志”&#xff0c;如下图所示 点开日志列表即可查看。

关于 CTF 中 php 考点与绕过那些事的总结

关于 CTF 中常见 php 绕过的总结可以参考我之前的博客&#xff1a; CTF之PHP特性与绕过 PHP特性之CTF中常见的PHP绕过-CSDN博客 其中主要介绍了 md5()、sha1()、strcmp、switch、intval、$_SERVER 函数、三元运算符、strpos() 、数组、非法参数名传参等相关的绕过。 在此基础上…