C/C++的指针与函数(指针函数与函数指针辨析)

发布时间:2026/11/14 17:48:19

C/C++的指针与函数(指针函数与函数指针辨析) 文章目录指针函数语法指针函数的工程应用---malloc与new函数指针函数的地址函数的地址与函数的返回值函数指针的声明使用函数指针的调用函数函数指针数组使用typedef为函数指针取别名函数指针的工程应用---回调函数callback指针函数指针函数就是指针的函数是个函数是一个返回值为指针的函数。什么叫指针的函数呢为了便于理解笔者自己引入了一下的概念。注意这只是便于理解而且是笔者自己想的如果有问题还请指正首先先从函数来说起函数可以分为两种一种是有返回值的一种是没有返回值的void声明。在有返回值这一类函数中有int、float等等因为这一类函数执行完毕后相当于他的返回值占据了函数名称的位置如下intadd(inta,intb){returnab;}intmain{intcadd(1,2);//这里相当于12这个int值占据了add(1,2)这个位置}所以我们可以说例子当中的函数是个int的函数。明确了这个概念之后接下来我们来理解指针的函数这个概念指针的函数也就是说函数的返回值是个指针。一个指针代替了原来函数的位置。语法返回类型* 函数名(参数列表);例如int*createArray(intsize){int*arr(int*)malloc(size*sizeof(int));for(inti0;isize;i){arr[i]i1;//这里的arr[i]相当于*(arri)如果不懂可以去看我的上一篇博客}returnarr;// 返回指向动态分配数组的指针}函数的返回值属性是一个指针这个指针的类型属性是整型int。指针函数的工程应用—malloc与newmalloc作为内存分配的重要函数其在stdlib.h文件中函数原型是void*malloc(size_t);malloc就是一个返回值为void*的指针的指针函数。new函数同理函数原型如下void*operatornew(size_t);new也是一个返回值为void*的指针的指针函数。函数指针函数指针可以理解为函数的指针是个指针是一个指向函数的指针。函数的地址指针和地址是分不开的我们要理解函数的指针首先先要了解函数的地址。在程序编译时函数的地址是如何确认的呢首先编译器将每个源文件.c 或 .cpp编译成目标文件.o 或 .obj时在目标文件中函数的地址是相对于文件起始位置的偏移量相对地址这是因为编译器还不知道最终的内存布局无法确定函数的绝对地址。在链接时链接器将多个目标文件合并成一个可执行文件.exe 或 .elf链接器会为函数确定一个最终的地址。函数的函数名就是函数的地址。#includestdio.hvoidmyFunction(){printf(Hello, World!\n);}intmain(){printf(Address of myFunction: %p\n,(void*)myFunction);return0;}输出结果为Address of myFunction:0x400526我们知道在编译完成后函数地址已经确认了接下来我们看一下在程序的执行过程中程序如何通过地址来调用执行函数。程序执行的本质时PC程序指针计数器不断加一运行所指向内存单元的代码。当程序执行到函数部分时即PC程序指针计数器指向函数时发生函数调用。第一步调用者将参数压入栈中。参数压入顺序通常根据调用约定不同压入的方式也不同常见的有cdecl、stdcall、fastcall第二步调用者将返回地址函数的下一条指令的地址压入栈中。第三步PC程序指针计数器会更新为被调用函数的地址从而跳转到函数的代码段执行。第四步函数即被调用者创建栈帧由序言代码执行完成将调用者的栈帧指针ebp压入栈。设置新的栈帧基址ebp esp。为局部变量分配空间保存重要寄存器的值第五步开始执行函数代码。第六步执行完毕后将返回值存储到寄存器当中。释放栈帧恢复调用者的栈帧指针。第七步从栈中弹出返回地址到PC指针计数器当中。至此函数调用完成程序继续执行。额外提及一点在单片机的中断执行过程中与程序函数调用过程类似可以帮助理解。函数的地址与函数的返回值辨析函数的地址与函数的返回值program(function1);//这里传入program函数的是function1函数的地址program(function1());//这里传入program函数的是function1函数的返回值二者仅有一对括号的差别注意辨析。第一个是为了在program函数中调用function1函数第二个是先调用function1函数如何将function1函数的返回值当作参数输入到program函数中去。函数指针的声明函数的函数名就是函数的地址这一点已经被我们反复提及如下intfunction(inta,intb);function就是地址接下来我们来看函数指针的声明intfunction(inta,intb);int(*pf)(inta,intb);pffunction;这里的pf就是函数function的指针这时候大家可能会有疑惑function是个地址*pf所替换的是个地址的位置而pf却被解释为了指针对指针进行 * 运算解应用运算不应该得到的是pf这个指针所存储的地址的指向的内容的值吗为什么是个地址这里笔者来给出解释上文提过函数名就是函数的地址这一点是不变的但是由于函数本身是在程序段进行的存储也就是代表着对于“函数”的理解绝不能等同于数据的理解实际上函数名代表着函数本身也是代表着函数的指针也就是说function *function function这三者是完全等价的存在。上面说的可能有点晕我们也可以这么来理解函数指针首先来看数据指针的定义过程。inta0;int*pa;paa;这里*并没有解引用的含义有的仅仅是声明的含义。同理在函数指针的定义过程中*也没有解引用的含义有的仅仅是声明的含义。intfunction(inta,intb);int(*pf)(inta,intb);pffunction;//这里将function理解为了函数的地址还有一种理解方式将function理解为函数本身。function是函数那么(*pf)也是函数(*pf)是个函数pf就是指针对指针进行解引用就得到了函数也就是(*pf)。intfunction(inta,intb);int(*pf)(inta,intb);pffunction;//这里将function理解为了函数本身讲到这里笔者也成功的将自己绕晕。其实本质上函数函数的地址函数的指针都是函数名这三者是一个东西。就是因为函数是存储在程序段当中的所以无法将函数的地址运算方式同数据的地址运算方式对等起来。function *function function使用函数指针的调用函数intadd(inta,intb);intmain(){int(*pf)(inta,intb);pfadd;inttest1add(1,2);inttest2(*pf)(1,2);//使用*来对指针进行解引用得到函数return0;}intadd(inta,intb){returnab;}实际上下面这种调用函数也是正确的inttest3pf(1,2);//pf为指针存储的是地址地址即为函数名在这里 C Primer Plus给出了解释感觉这种设计真的是难以理解不过确实也证实了上面提及的函数函数的地址函数的指针都是函数名这三者是一个东西函数指针数组语法返回类型(*函数指针[n])(参数列表);//例子void(*funcPtrArray[3])();关于为啥在这个位置加上[ n ]我认为 C Primer Plus这里的这个解释很好我之间粘到下面。使用typedef为函数指针取别名常见的typedef的使用方法为typedef原类型 新类型名;但是在函数指针这里略微不同其语法格式为typedef返回类型(*函数指针)(参数列表);typedefvoid(*PF)(int);// 定义 PF为函数指针类型的别名实际上在这里原类型是返回类型 ( * )(参数列表)即void ( * )(int)而新类型名则是对应函数指针即PF。这样我们在创建一个void ( * )(int)形式的函数指针时就可以使用如下的形式PF pf;//相当于以下形式typedefvoid(*pf)(int);函数指针的工程应用—回调函数callback// 回调函数类型typedefvoid(*Callback)(int);// 接受回调函数作为参数的函数voidprocess(intvalue,Callback callback){printf(Processing value: %d\n,value);callback(value);// 调用回调函数}// 回调函数实现voidprintValue(intvalue){printf(Callback: %d\n,value);}intmain(){process(10,printValue);// 传递函数指针return0;}上述例子中使用了函数指针的方式创建回调函数还有一种弱定义__weak的方式相信学过STM32单片机HAL库一定不会对回调函数陌生在HAL库中就是这种弱定义__weak的方式。这篇文章主要是将函数指针的所以在这里就不多赘述关于弱定义的内容了。为什么要使用回调函数为了实现低耦合编程代码之间的耦合度过高会导致难以移植修改等问题使用回调函数就可以将部分的实现分离出去比如在单片机中中断处理的函数就是以回调函数的形式出现的用户只需要修改回调函数满足功能即可不用修改整个中断服务函数
延伸阅读

更多相关文章

2026/11/10 6:22:33

C/C++的指针与常量const

指针与常量常规变量的地址赋给const修饰的指针指向常量的指针指针常量指向常量的指针常量总结const修饰的常量的地址赋给const修饰的指针指向常量的指针指向常量的指针常量总结常规变量的地址赋给const修饰的指针 注意,以下三种情况中的例子中的a和b都没有被const修…

2026/11/10 11:42:32

虚拟机中zynq下BRAM读写和网口测试

文章目录一、内容介绍二、实现步骤2.1 petalinux和vivado配置步骤2.1.1 vivado配置2.1.2 petalinux配置2.2 linux系统(串口)2.2.1 u-boot系统2.2.2 linux系统2.3 petalinux和vivado相关2.3.1 TCP服务器程序2.3.2 BRAM读写一、内容介绍 ZYNQ的PL端读写BR…

2026/11/14 17:47:21

在郑州哪里学电工证良心建议:学历不高也能轻松报名

在郑州哪里学电工证良心建议:学历不高也能轻松报名 你是不是也在纠结“在郑州哪里学电工证”?怕自己学历不高报不上名?别担心,我来告诉你一个 良心建议 :只要符合报考条件,学历不是问题,关键是你怎么选对报名机构。…

2026/11/14 17:47:21

电工证怎么考唐山怎么拿电子证书

电工证怎么考唐山怎么拿电子证书 你是不是也遇到过这种情况, 不知道去哪报名怕被中介坑 ,好不容易找到个报名点,结果要么收费高得离谱,要么压根不靠谱?尤其是 电工证怎么考唐山 这样的问题,很多人一上来就懵了。其实,只要你掌握了正确的流程,…

2026/11/14 17:47:21

宣城低压电工证怎么选?良心建议帮你避开这些坑

宣城低压电工证怎么选?良心建议帮你避开这些坑 之前考的证在外省能不能转过来?这个问题我听得太多了,尤其是像你这样在周口做中小型施工企业负责人的朋友,很多时候跑项目、做工程,跨省工作是常态。可证书不认,那岂不是白忙活?今天我就从一个干了十年的…

2026/11/14 17:47:21

南阳考电工证考场在哪千万别踩坑

南阳考电工证考场在哪千万别踩坑 怕考不过白交培训费,南阳考电工证考场在哪,报名前这些坑你必须知道。电工证是进入电气行业的门槛,但很多人因为不懂流程、选错培训机构,结果钱花了却没拿到证,甚至考试都不知道在哪考。别再走弯路了,今天就从南阳考电工…

2026/11/14 17:42:21

电工作业其他称呼含金量高不高?低学历也能拿证

电工作业其他称呼含金量高不高?低学历也能拿证 你是不是也担心, 学历不高怕报不上名 ?电工作业在行业内还有不少其他称呼,比如“电气操作工”“电工技师”“配电工”等等,但不管叫什么,只要能拿到证,含金量照样摆在那儿。很多低学历的朋友其实也能顺…

2026/11/13 22:33:32

电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。…

2026/11/14 0:06:39

土木特种工考证官方报名入口怎么找 之前考的证在外省能不能转过来

土木特种工考证官方报名入口怎么找 之前考的证在外省能不能转过来 之前考的证在外省能不能转过来?这个问题我太熟悉了,作为一名干了十几年的特种作业证书办理从业者,每年都会遇到不少像你一样在外地考了证,回来却发现无法直接使用的学员。别急,今天我就…

2026/11/14 0:06:39

电工证要多久多钱保姆级教程:工地太忙根本没时间复习考试

电工证要多久多钱保姆级教程:工地太忙根本没时间复习考试 工地太忙根本没时间复习考试,你不是一个人。在信阳浉河区,很多刚进入工地的电工都面临这样的困境:工作强度大,时间碎片化,根本没有系统复习考试的机会。但电工证是上岗的硬门槛,…

2026/11/13 22:32:11

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/13 12:14:39

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑