【C语言】指针(4)

一、回顾

 在这之前,我们学习了很多关于指针的内容,我们先在这里简单的回顾一下。

1、一级指针

int* p;    -- 整形指针-指向整形的指针 

char* p; ...

void* p;...

...

2、二级指针

int** p; 

char** p;

...

3、数组指针 -- 指向数组的指针

int (*p)[ ];

int main(){int arr[3] = {1,2,3};int (*parr)[3] = &arr;
return 0;
}

4、指针数组 -- 存放指针的数组,本质就是数组。

 int* arr[ ];

int main(){int a[] = {1,2,3,4,5};int b[] = {2,3,4,5,6};int c[] = {3,4,5,6,7};int* arr[] = {a,b,c};for(int i=0;i<3;i++){for(int j=0;j<5;j++){printf("%d ",*(arr[i] + j));}printf("\n");}return 0;
}

二、函数指针

 1、理解

指向函数地址的指针

 2、写法

 函数返回类型 (* p)(参数1、参数2、...)

 3、举例

int Add(int x,int y){return x + y;
}
int main(){int (*p)(int ,int ) = &Add;printf("%p\n",&Add);printf("%p\n",Add);return 0;
}

 在前面一节中将到了  数组名和&数组名的区别、但在这里 函数名 == &函数名。

4、使用

由于 函数名 ==  &函数名。所以可以有多种调用方法。

int Add(int x,int y){return x + y;
}
int main(){int (*p)(int ,int ) = &Add;int ret = (*p)(20,6);
//	int ret = p(20,6);
//	int ret = Add(20,6);printf("%d\n",ret);return 0;
}

5、试解析下列的一段代码

(*(void ( * ) () ) 0 ) ( ) ;

e832363829ad4b49a9e45762ba6e2e02.png

三、函数指针数组

1、理解

存放函数指针的数组、存放同类型的函数指针。

 2、写法

  函数返回类型 (* pArr [ ])(参数1、参数2、...)

 3、举例  --  简单计算器的实现

void menu(){printf("***********************\n");printf("*****1、Add    2、Sub**\n");printf("*****3、Mul    4、Div**\n");printf("*****    0、exit     **\n");printf("***********************\n");
}
int Add(int x,int y){return x + y;
}
int Sub(int x,int y){return x - y;
}
int Mul(int x,int y){return x * y;
}
int Div(int x,int y){return x / y;
}
int main(){int input = 0;do{int x = 0, y = 0, ret = 0;int (*parr[5])(int, int) = {NULL,Add,Sub,Mul,Div};menu();printf("请选择要实现的功能:");scanf("%d",&input);if(input >= 1 && input <=4){printf("请输入两个操作数:");scanf("%d %d",&x , &y);ret = (*parr[input])(x,y);printf("ret=%d\n",ret);}else if(input == 0){printf("退出程序\n");break;}else{printf("输入错误,重新输入\n");}}while(input);return 0;
}

4、* 指向函数指针数组的指针

void test(const char* str ){printf("%s\n",str);
}
int main(){void (*p)(const char*) = test; //函数指针pvoid (*parr[2])(const char*) = { test , NULL}; //函数指针数组parrvoid (*(*p3)[2])(const char*) = &parr;// 指向函数指针数组的指针return 0;
}

四、回调函数

1、概念理解

通过函数指针调用的函数。 ---  把一个函数的地址(指针)作为参数传递给另一个函数,当这个指针被用来调用其所指的函数时,就称它为回调函数。

 2、举例说明 --  库函数 qsort 的使用

#include<stdio.h>
#include <stdlib.h>   // qsort头文件
// qsort 函数
//  void qsort (void* base, //指向待排序的首元素地址。
//			size_t num,     //待排序的元素个数
//			size_t size,	//待排序元素的大小,单位时字节
//			int (*compar)(const void*,const void*)); //待排序元素的比较方式int compare (const void * a, const void * b)
{return ( *(int*)a - *(int*)b );
}
int main ()
{int arr[] = {14,78,24,69,10};int sz = sizeof(arr) / sizeof(arr[0]);qsort (arr, sz, sizeof(arr[0]), compare);for (int i=0; i<sz ; i++)printf ("%d ",arr[i]);return 0;
}

 3、举例 --  模拟qsort实现冒泡排序升级版

#include<stdio.h>
//   函数实现
void swap(char* a , char* b , int size){for(int i=0;i<size;i++){char tmp = *a;*a = *b;*b = tmp;a++;b++;}
}
void bubblePP(void* base,  //指向待排序的首元素地址int num,       //待排序的元素个数int size,      //待排序元素的大小,单位是字节int (*compar)(const void* ,const void* )){  //待排序元素的比较方式 for(int i=0;i<num ;i++){for(int j=0;j<num - i - 1;j++){if(compar((char*)base +j*size , (char*)base + (j+1)*size) > 0){swap((char*)base +j*size , (char*)base + (j+1)*size , size);}}}
}//  用户输入
int compar (const void * a, const void * b)
{return ( *(int*)a - *(int*)b );
}void print(int arr[], int sz){for(int i=0;i<sz;i++){printf("%d ",arr[i]);}printf("\n");
}
void test1(){int arr[] = {14,78,24,69,10};int sz = sizeof(arr) / sizeof(arr[0]);print(arr, sz);                          //排序之前打印bubblePP(arr,sz,sizeof(arr[0]),compar);  // 排序print(arr, sz);                          //排序之后打印
}
//void test2(){
//	char arr[] = {'w','m','z','d'};
//		int sz = sizeof(arr) / sizeof(arr[0]);
//		print(arr, sz);  // 要使 compar 和 print 的类型参数与这里的相对应
//		bubblePP(arr,sz,sizeof(arr[0]),compar);  // 排序
//		print(arr, sz);
//}
int main(){test1();
//	test2();return 0;
}

要点分析:

在函数内部,并不知道用户传递给我们的数据类型,所以根据最小的char类型以及待排序的元素大小size,来确定下一个元素的位置。

 这里依然是和上面一样的问题,所以在swap交换的时候采用一字节一字节的交换方式,并以元素大小size为限制表示一个元素是否交换完成。​​​​​​

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

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

相关文章

3038. 相同分数的最大操作数目 I(Rust模拟击败100%Rust用户)

题目 给你一个整数数组 nums &#xff0c;如果 nums 至少 包含 2 个元素&#xff0c;你可以执行以下操作&#xff1a; 选择 nums 中的前两个元素并将它们删除。 一次操作的 分数 是被删除元素的和。 在确保 所有操作分数相同 的前提下&#xff0c;请你求出 最多 能进行多少次…

Python | Leetcode Python题解之第136题只出现一次的数字

题目&#xff1a; 题解&#xff1a; class Solution:def singleNumber(self, nums: List[int]) -> int:return reduce(lambda x, y: x ^ y, nums)

Vue07-MVVM模型

一、MVVM模型的定义 M&#xff1a;模型&#xff08;model&#xff09;&#xff1a;对应data中的数据&#xff1b;V&#xff1a;视图&#xff08;view&#xff09;&#xff1a;模版&#xff1b;VM&#xff1a;视图模型&#xff08;ViewModel&#xff09;Vue的实例对象。 Vue.js…

WSDM2022推荐系统相关论文整理(一)

2022年第15届国际网络搜索与数据挖掘会议WSDM在2022年2月21日到25日于线上举行&#xff0c;共收到了786份有效投稿&#xff0c;最终录取篇数为159篇&#xff0c;录取率为20.23%。作为主流的搜索与数据挖掘会议&#xff0c;论文的话题主要侧重于搜索、推荐以及数据挖掘领域&…

第二证券炒股知识:北交所的股票是a股吗?是主板吗?

北交所的股票是a股&#xff0c;但不属于主板&#xff0c;是一个单独的板块。 A股主板是在上海证券买卖所或许深圳证券买卖所上市的公司&#xff0c;主板通常是大盘股&#xff0c;多为商场占有率高、规划大、盈余安稳良好的大型企业。沪市主板以600、601或603最初&#xff0c;深…

(学习笔记)数据基建-数据安全

&#xff08;学习笔记&#xff09;数据基建-数据安全 数据安全数据安全实施难点数据安全保障流程数据安全措施实施阶段数据安全如何量化产出数据安全思考 数据安全 数据安全问题是最近比较热的话题&#xff0c;数据泄漏引发的用户信任危机事件也比比皆是&#xff0c;以及跨部门…

一个案例,剖析攻防演练中威胁溯源的正确姿势

一年一度的攻防演练即将拉开帷幕。“威胁溯源”一直是演练活动中一个十分重要的工作项&#xff0c;它不仅有助于理解和分析攻击的来源、方法和动机&#xff0c;还能够显著提升整体安全防护水位&#xff0c;提升组件与人员的联动协作能力。在真实的攻击场景中&#xff0c;溯源工…

verilog 232串口通信程序

1,串口通信协议: 通常串口的一次发送或接收由四个部分组成:起始位S、数据位D0~D7(一般为 6 位~8 位之间可变,数据低位在前)、校验位(奇校验、偶检验或不需要校验位)、停止位(通常为1位、1.5位、2位)。停止位必须为逻辑 1。在一次串口通信过程中,数据接收与发送双方…

[STM32]定位器与PWM的LED控制

目录 1. 深入了解STM32定时器原理&#xff0c;掌握脉宽调制pwm生成方法。 (1)STM32定时器原理 原理概述 STM32定时器的常见模式 使用步骤 (2)脉宽调制pwm生成方法。 2. 实验 (1)LED亮灭 代码 测试效果 (2)呼吸灯 代码 测试效果 3.总结 1. 深入了解STM32定时器原…

Redis使用中的性能优化——搭建Redis的监测服务

大纲 环境安装配置Redis安装 安装配置redis_exporter编译运行 安装启动Prometheus创建用户下载并解压修改配置启动 安装启动grafana安装启动 测试参考资料 抛开场景和数据&#xff0c;谈论性能优化&#xff0c;就是纸上谈兵。这个系列我们将通过相关数据来展现常见的Mysql优化前…

微信小程序多端框架打包后发布到APP Store

IPA 上架 App Store 生成 iOS 证书和 Provisioning Profile iOS 开发者账号缴/续费的发票查看和获取 个人开发者把小程序发布到 App Store 5个步骤&#xff08;保姆级教程&#xff09; 一、参数的设置、证书的生成、生成profile文件 微信小程序多端应用Donut IOS相关的参数…

互联网轻量级框架整合之SpringMVC初始化及各组件工作原理

Spring MVC的初始化和流程 MVC理念的发展 SpringMVC是Spring提供给Web应用领域的框架设计&#xff0c;MVC分别是Model-View-Controller的缩写&#xff0c;它是一个设计理念&#xff0c;不仅仅存在于Java中&#xff0c;各类语言及开发均可用&#xff0c;其运转流程和各组件的应…

使用Ollama+OpenWebUI部署和使用Phi-3微软AI大模型完整指南

&#x1f3e1;作者主页&#xff1a; 点击&#xff01; &#x1f916;AI大模型部署与应用专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年6月6日23点50分 &#x1f004;️文章质量&#xff1a;96分 欢迎来到Phi-3模型的奇妙世界&#xff01;Phi-3是由微软…

网络安全:https劫持

文章目录 参考https原理https窃听手段SSL/TLS降级原理难点缺点 SSL剥离原理发展缺点前端劫持 MITM攻击透明代理劫持 参考 https原理 SNI 浏览器校验SSL证书 https降级 https握手抓包解析 lets encrypt申请证书 https原理 步骤如下&#xff1a; 客户端向服务器发送https请求。…

动态IP与静态IP的优缺点

在网络连接中&#xff0c;使用动态和静态 IP 地址取决于连接的性质和要求。静态 IP 地址通常更适合企业相关服务&#xff0c;而动态 IP 地址更适合家庭网络。让我们来看看动态 IP 与静态 IP 的优缺点。 1.静态IP的优点&#xff1a; 更好的 DNS 支持&#xff1a;静态 IP 地址在…

MATLAB基础应用精讲-【数模应用】二元Logit分析(最终篇)(附python、MATLAB和R语言代码实现)

目录 算法原理 SPSSAU 1、二元logistic分析思路说明 2、如何使用SPSSAU进行二元logistic操作 3、二元logistic相关问题 算法流程 一、分析前准备 1、确定分析项 2.多重共线性判断 3.数据预处理 二、回归基本情况分析 三、模型拟合评价 1、似然比检验 2、拟合优…

晶圆几何量测系统支持半导体制造工艺量测,保障晶圆制造工艺质量

晶圆面型参数厚度、TTV、BOW、Warp、表面粗糙度、膜厚、等是芯片制造工艺必须考虑的几何形貌参数。其中TTV、BOW、Warp三个参数反映了半导体晶圆的平面度和厚度均匀性&#xff0c;对于芯片制造过程中的多个关键工艺质量有直接影响。 TTV、BOW、WARP对晶圆制造工艺的影响 对…

详细分析Mysql中的 JSON_ARRAYAGG 基本知识(附Demo)

目录 1. 基本知识2. Demo2.1 简单聚合2.2 带排序聚合2.2.1 子查询进行排序2.2.2 创建临时表 2.3 带条件聚合2.4 多列聚合2.5 嵌套 JSON 结构 1. 基本知识 JSON_ARRAYAGG为 SQL 聚合函数&#xff0c;用于将一组值聚合为一个 JSON 数组 多行结果组合成一个 JSON 数组形式的场景…

企业研发数据泄露损失严重,研发数据保护到底怎么才能有效落地?

数据已成为企业毋庸置疑的核心资产&#xff0c;而企业众多数据中&#xff0c;研发数据则占据着重要的角色&#xff0c;近年来&#xff0c;发生了多起企业研发数据被窃取或泄露的事件&#xff0c;给企业带来严重的名誉、经济损失&#xff1a; 小米公司&#xff1a;2023年1月&am…

Linux驱动应用编程(三)UART串口

本文目录 前述一、手册查看二、命令行调试串口1. 查看设备节点2. 使用stty命令设置串口3. 查看串口配置信息4. 调试串口 三、代码编写1. 常用API2. 例程线程优化 前述 在开始实验前&#xff0c;请一定要检查测试好所需硬件是否使用正常&#xff0c;不然调试过程中出现的问题&am…