函数指针和指针函数

指针

指针函数

指针函数一个函数,只不过这个函数的返回值是一个地址值

  • 和普通函数唯一的区别就是在函数名前面多了一个*号

    函数返回值必须用同类型的指针变量来接受

    也可以将其返回值定义为 void*类型,在调用的时候强制转换返回值为自己想要的类型

struct Data{int a;char b;void show(){cout << a << "," << b << endl;}
};
//指针函数
Data* fun(int a,char b){Data *tmp = new Data;tmp->a = a;tmp->b = b;return tmp;
}
int main(){Data *aa = fun(100, 'c');aa->show();return 0;
}

采用强制类型转换

//指针函数,返回值改为void*
void* fun(int a,char b){Data *tmp = new Data;tmp->a = a;tmp->b = b;return tmp;
}
int main(){//强制类型转换Data *aa = static_cast<Data*>(fun(200,'v'));aa->show();return 0;
}

例子2:

int *f(int, int);
int main(){
int *p = nullptr;
p = f(100, 200);
cout << "The memory addr is" << p << endl;
cout << "The value is" << *p << endl;
return 0;
}
//函数定义
int* f(int a,int b){
int *p = new int;
cout << "The memory addr is" << p << endl;
*p = a * b;
cout << "The value is" << *p << endl;
return p;
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

发现输出的地址是相同的

指针函数就是返回一个地址给调用者,用于需要地址的情况

函数指针

函数指针就是一个指针,但这个指针指向的函数,不是普通的基本数据类型或者类对象。

指向函数的指针包含了函数的地址,可以通过它来调用函数

函数指针就是指向函数的指针

int sum(int a,int b){
return a + b;
}
int mul(int a,int b){
return a * b;
}
//函数指针:指向函数的指针
int (*fun)(int, int);
int main(){
fun = sum;
cout << fun(100, 200) << endl;
fun = &mul;
cout << (*fun)(20, 30) << endl;
return 0;
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
例子

#include <iostream>
using namespace std;int max(int x, int y){return x > y ? x : y;
}
int min(int a,int b){return a < b ? a : b;
}
int main(void){int (*p)(int, int) = max;int (*q)(int, int) = &min;cout<<(*p)(300, p(100, 200))<<endl;cout << q(99, (*q)(33, 77)) << endl;
}

可以连续调用

struct Data{int a;int b;Data(int a,int b):a(a),b(b){}
};
int col(Data x,Data y){return x.a + y.a+ x.b + y.b;
}
int main(void){Data aa(3, 4);Data bb(5, 6);//赋值的函数名,取不取地址都可以int (*point)(Data, Data) =col;//&cal//函数指针调用cout << point(aa, bb) << endl;cout << (*point)(bb, bb) << endl;
}

函数指针赋值,参数表类型必须和函数名类型匹配

int (*point)(Data, Data) =col;

千万不要加参数,因为指针赋值地址

函数指针可以当回调函数

函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的函数。

说白了就是回调函数参数里面存在函数指针

把一段可执行的代码像参数传递那样传给其他代码,而这段代码会在某个时刻被调用执行,就叫做回调。
--如果代码立即被执行就称为同步回调;
--如果在之后晚点的某个时间再执行,则称为异步回调。
int add(int a,int b){return a + b;
}
int mul(int c,int d){return c * d;
}
void getNUm1(vector<int>& vec,int (*p)(int,int),int (*q)(int,int)){for (int i = 1; i < vec.size();i++){cout << p(vec[i], vec[i - 1]) << ",";cout << q(vec[i], vec[i - 1]) << endl;}
}
void getNUm2(vector<int>& vec,int (*p)(int,int),int (*q)(int,int)){for (int i = 1; i < vec.size();i++){cout << (*p)(vec[i], vec[i - 1]) << ",";cout << (*q)(vec[i], vec[i - 1]) << endl;}
}
int main(void){vector<int> vec = {1, 2, 3, 4, 5};getNUm1(vec, add, mul);getNUm2(vec, &add, &mul);
}

总结

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 指针函数:返回值是一个指针的函数
  • 函数指针:指向一个函数地址的指针

数组指针

一个指针指向一个数组

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

int main(void){int temp[6] = {1, 2, 3, 4, 5, 6};for (int i = 0; i < 6;i++){cout << *(temp + i) << "," << temp[i] << ",";}cout << endl;int *p = temp; //&temp[0]for (int i = 0; i < 6;i++){cout << *(p + i) << "," << p[i] << ",";}
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

 int a[5] = {10, 20, 30, 40, 50};int(*p)[5] = &a;//把数组a的地址赋给p,则p为数组a的地址for (int i = 0; i < 5;i++){cout << *(*p + i) << "," << (*p)[i] << endl;}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

指向二维数组

  int a[3][5] = {{1, 2, 3, 4, 5},{6, 7, 8, 9, 10},{11, 12, 13, 14, 15}};int(*p)[5] = a;//&a[0]for (int i = 0; i < 3;i++){for (int j = 0; j < 5;j++){cout << (*p)[j] <<" ";}cout << endl;++p;}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这里是把数组第一个元素赋值给p,因为二维数组在内存也是占一行的,不能赋值整个数组

int a[3][5] = {1, 2, 3, 4, 5,6, 7, 8, 9, 10,11, 12, 13, 14, 15};

&a[0]==&*(a+0)==a

注意p+1后,整个数组移动5个步长

二维数组的指向

int a[3][5] = {{1, 2, 3, 4, 5},{6, 7, 8, 9, 10},{11, 12, 13, 14, 15}};for (int i = 0; i < 3; i++){for (int j = 0; j < 5; j++){cout << a[i][j] << " ";cout << *(a[i] + j) << " ";cout << *(*(a + i) + j) << " ";cout << (*(a + i))[j] << " ";}cout << endl;}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


数组指针的行大小只要和数组吻合,可以把数组任意一行赋给它

利用:&a[i]或者a+i,都代表第i行

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

 int a[3][5] = {{1, 2, 3, 4, 5},{6, 7, 8, 9, 10},{11, 12, 13, 14, 15}};int(*q)[5] = a + 1;for (int i = 0; i < 5;i++){cout << (*q)[i] << " ";}cout << endl;int(*p)[5] = &a[2];for (int i = 0; i < 5;i++){cout <<*((*p)+i) << " ";}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


 int a[3][5] = {{1, 2, 3, 4, 5},{6, 7, 8, 9, 10},{11, 12, 13, 14, 15}};int(*p)[5] = a;for (int i = 0; i < 3;i++){for (int j = 0; j < 5;j++){cout << p[i][j] << ",";cout << (*(p+i))[j] << ",";cout << *(p[i]+j) << ",";cout << *(*(p+i)+j) << ",";}cout << endl;}

同样p [ i ] [ j ]可以访问到元素


 int a[3][5] = {{1, 2, 3, 4, 5},{6, 7, 8, 9, 10},{11, 12, 13, 14, 15}};int(*p)[5] = a+1;//指向了第二行for (int i = 0; i < 2;i++){for (int j = 0; j < 5;j++){//注意:(*())[j]的括号en不可省cout << (*(p+i))[j] << ",";}cout << endl;}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

指针数组

指针数组

一个由n个指针类型元素组成的指针数组,或者说这个当一个数组里含有的元素为指针类型的时候,它就被成为指针数组

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

int a=100;int b = 200;int c = 300;int *p[3];//数组类型为n指针p[0] = &a;p[1] = &b;p[2] = &c;for (int i = 0; i < 3;i++){cout << *p[i] << endl;}

p[i]是指针,所以*(p[i])才能取到值但是[]优先级更高,不必加括号

 int arr[3][4] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}};int *p[3];//指针数组for (int i = 0; i < 3;i++){cout << arr[i]<<","<<arr+i<<","<<*(arr+i) << endl;p[i] = arr[i];}for (int i = 0; i < 3;i++){for (int j = 0; j < 4;j++){cout << p[i][j] << ",";}cout << endl;}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

发现:arr[i]和arr+i和*(arr+i)都是表示的地址

同理:p[i] [j]可以写成等价的四种形式


    int a[3] = {1, 2, 3};int b[3] = {4, 5, 6};int c[3] = {7, 8, 9};int *p[3]; // 指针数组p[0] = a;p[1] = b;p[2] = &c[0];for (int i = 0; i < 3; i++){for (int j = 0; j < 3;j++){cout << *(p[i]+j) << ",";}cout << endl;}

扩展

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

首先记住:

返回值 (*函数名)(含参表)一定是个函数指针

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

有含参数表,在函数名内部写成:指针数组

上图是:指向函数的指针数组的指针

int Add(int x, int y) {return x + y;
} int main() {//函数指针int(*pAdd)(int, int) = Add;//&Add//函数指针的数组int (*pArr[5])(int, int);//指向函数指针数组的指针——基于函数指针的数组去写int (*(*ppArr)[5])(int, int)=&pArr;return 0;
}

用变量a给出如下定义:

*函数指针数组首先是个数组。这个数组(包含 6 个元素),每个元素都是一个函数指针。

int (*a[10])(int)

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

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

相关文章

一、selenium自动化简介selenium工具集

文章目录 一、简介二、组成部分三、selenium工具集3.1 Selenium IDE3.2 Selenium WebDriver3.3 Selenium Grid3.4 Appium 一、简介 官方网站 Selenium 是支持 web 浏览器自动化的一系列工具和库的综合项目。 它提供了扩展来模拟用户与浏览器的交互&#xff0c;用于扩展浏览器分…

Excel使用VLOOKUP公式匹配不出正确公式,返回#N/A

问题&#xff1a; Excel使用VLOOKUP公式匹配不出正确公式&#xff0c;返回#N/A 原因&#xff1a; 原数据和匹配的数据格式不一致 解决办法&#xff1a; 把格式都设置为文本。 例如添加一列&#xff0c;输入英文符号&#xff0c;然后把数据源拼接起来&#xff0c;转换为文…

Linux入门攻坚——31、rpc概念及nfs和samba

NFS&#xff1a;Network File System 传统意义上&#xff0c;文件系统在内核中实现 RPC&#xff1a;函数调用&#xff08;远程主机上的函数&#xff09;&#xff0c;Remote Procedure Call protocol 一部分功能由本地程序完成 另一部分功能由远程主机上的 NFS本质…

java实操(二)-酒店管理系统

一、题目 使用二维数组实现酒店管理系统。功能如下&#xff1a; 1.查看酒店所有房间的状态 2.预定房间 3.退房 4.退出系统 二、程序 1.Hotel.java package Hotel;public class Hotel {private int id;private String standard;private String status;public Hotel() {}…

基于阿里云函数计算(FC)x 云原生 API 网关构建生产级别 LLM Chat 应用方案最佳实践

作者&#xff1a;计缘 LLM Chat 应用大家应该都不陌生&#xff0c;这类应用也逐渐称为了我们日常的得力助手&#xff0c;如果只是个人使用&#xff0c;那么目前市面上有很多方案可以快速的构建出一个LLM Chat应用&#xff0c;但是如果要用在企业生产级别的项目中&#xff0c;那…

【ORACLE】substr() 函数

在 Oracle 数据库中&#xff0c;SUBSTR() 函数用于从字符串中提取子字符串。这个函数非常灵活&#xff0c;可以根据不同的需求提取字符串的不同部分。 函数语法 SUBSTR() 函数的基本语法如下&#xff1a; SUBSTR(string, start, length)string&#xff1a;要提取子字符串的原…

C#高级:递归2-根据ID反向递归求其所有的祖先节点信息

目录 一、实现demo 二、封装方法 【ID>祖先ID】 【ID>祖先实体】 三、递归讲解 一、实现demo class MainClass {static List<Person> PersonList new List<Person>(){new Person(){ Id1,ParentIDnull,Name"小明曾祖父",},new Person(){ Id2…

python文件自动化(4)

接上节课内容&#xff0c;在开始正式移动文件到目标文件夹之前&#xff0c;我们需要再思考一个问题。在代码运行之前&#xff0c;阿文的下载文件夹里已经存在一些分类文件夹了&#xff0c;比如图例中“PDF文件”这个文件夹就是已经存在的。这样的话&#xff0c;在程序运行时&am…

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext new ClassPathXmlApplicationContext("bean.xml"); } BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanFactory的功能相似&#xff0c;都是…

linux 安装redis

1. 更新系统和安装依赖 sudo apt update sudo apt install build-essential tcl2. 下载 Redis 源码(没有opt文件夹&#xff0c;则先创建opt文件夹) cd /opt wget http://download.redis.io/releases/redis-6.2.6.tar.gz3. 解压和编译 Redis 解压下载的文件&#xff0c;并进入…

Qt/C++编写的Onvif调试助手调试神器工具/支持云台控制/预置位设置等/有手机版本

一、功能特点 广播搜索设备&#xff0c;支持IPC和NVR&#xff0c;依次返回。可选择不同的网卡IP进行对应网段设备的搜索。依次获取Onvif地址、Media地址、Profile文件、Rtsp地址。可对指定的Profile获取视频流Rtsp地址&#xff0c;比如主码流地址、子码流地址。可对每个设备设…

AtCoder Beginner Contest 370-C~D题解

AtCoder Beginner Contest 370-C题解 思路 整体来说&#xff0c;一眼是一个贪心&#xff0c;具体来说先把让字典序变小的字符变化&#xff0c;让后再让字典序变大的字符变化 代码 #include <bits/stdc.h> using namespace std; char s[105],t[105]; int a[105],sum; …

深入了解以太坊

1. 以太坊编程语言和操作码 以太坊中智能合约的代码以高级语言编写&#xff0c;如 Serpent、LLL、Solidity 或 Viper,并可转换为 EVM 可以理解的字节码&#xff0c;以便执行。 Solidity 是为以太坊开发的高级语言之一&#xff0c;它具有类似 JavaScript 的语法&#xff0c;可以…

用广播星历计算卫星运动的平均角速度

用广播星历计算卫星位置 1.计算卫星运动的平均角速度 首先根据广播星历中给出的参数计算参考时刻的平均角速度: 式中&#xff0c;GM为万有引力常数G与地球总质量M之乘积&#xff0c;其值为GM3.98600510^14b m3/s2。 然后根据广播星历中给定的摄动参数计算观测时刻卫星的平均…

使用AI写WebSocket知识是一种怎么样的体验?

一、WebSocket基础知识 1. WebSocket概念 1.1 为什么会出现WebSocket 一般的Http请求我们只有主动去请求接口&#xff0c;才能获取到服务器的数据。例如前后端分离的开发场景&#xff0c;自嘲为切图仔的前端大佬找你要一个配置信息的接口&#xff0c;我们后端开发三下两下开…

JDBC:连接数据库

文章目录 报错 报错 Exception in thread “main” java.sql.SQLException: Can not issue SELECT via executeUpdate(). 最后这里输出的还是地址&#xff0c;就是要重写toString()方法&#xff0c;但是我现在还不知道怎么写 修改完的代码&#xff0c;但是数据库显示&#…

STL-详细介绍list

目录 一、含义介绍 二、遍历&#xff08;迭代器和范围for&#xff09; 三、部分接口介绍 1.将两个有序链表归并成一个&#xff1a;merge&#xff08;&#xff09; 2、去重&#xff1a;unique&#xff08;&#xff09; 3、将一个链表或链表的结点或链表的迭代器区间插入到另…

2. 下载rknn-toolkit2项目

官网链接&#xff1a; https://github.com/airockchip/rknn-toolkit2 安装好git&#xff1a;[[1. Git的安装]] 下载项目&#xff1a; git clone https://github.com/airockchip/rknn-toolkit2.git或者直接去github下载压缩文件&#xff0c;解压即可。

ASIO网络调试助手之一:简介

多年前&#xff0c;写过几篇《Boost.Asio C网络编程》的学习文章&#xff0c;一直没机会实践。最近项目中用到了Asio&#xff0c;于是抽空写了个网络调试助手。 开发环境&#xff1a; Win10 Qt5.12.6 Asio(standalone) spdlog 支持协议&#xff1a; UDP TCP Client TCP Ser…

【VUE】跨域问题的概念,以及解决方法。

目录 1.跨域概念 2.解决方法 2.1 配置网络请求代理 2.2 使用CrossOrigin 注解 2.3 通过配置文件实现跨域 2.4 添加 CorsWebFilter 来解决跨域问题 1.跨域概念 跨域问题是由于浏览器实施了同源策略&#xff0c;该策略要求请求的域名、协议和端口必须与提供资源的服务相同。…