白话函数指针

简介: 白话函数指针

什么是函数?


从本质意义上讲,函数就是用来完成一定功能的。针对于编译型语言来说,编译器会将函数编译成一段具有特定功能的可执行代码块。函数的定义包含三个重要部分(返回类型、参数类型、调用约定)。


什么是指针?


一种特殊的变量,用来保存地址值,某类型的指针指向某类型的地址。


何为函数指针?


就是一种特殊的指针——指向一个函数的指针,其保存的值就是函数的地址。


函数是如何被调用的?


在(机器码)汇编语言层面,调用一个函数(过程), 通过call指令完成,通常用call+函数地址完成函数调用,因此,针对于底层的机器码,只需要知道一个函数的地址和传参模式,即可完成函数调用。




函数指针如何定义?


任何变量定义都包含三部分: 变量类型 + 变量名 = 初值,那么定义一个函数指针,首先我们需要知道要定义函数指针(指针类型)。

int __stdcall AddImplement(int a, int b) 
{    return a + b;
}

这个函数的类型是有两个整型参数,函数调用约定为__stdcall,返回值是个整型, 对应的函数指针类型为:

int(__stdcall *)(int a, int b)

定义类型时候,参数名是也可去掉的(只需要关系函数的本质定义:返回类型、参数类型、调用约定)

int(__stdcall *)(int, int)

并且可以用typedef将其命令:

typedef int(__stdcall *fnAdd)(int a, int b);

这个时候fnAdd就等价于:

int(__stdcall *)(int, int)

注意:在作为一个长期接触函数指针或者动态调用的开发人员,必须要注意什么函数指针类型时候,是否和真实需要调用的函数调用约定保持一致,如果不一致,会导致汇编代码传递参数的方式不正确,直接造成栈溢出。




接下来,咱们通过三个例子来深入理解函数指针。


1. 加法函数实例


image.png

image.png

我们从VS调试工具和输出中同时都得到fAdd的值是0x00CE1210,在内存中得到0x00CE1210地址开始的值分别是

0x55 0x8b 0xec 0x8b 0x45 0x08 0x03 0x45 0x0c 0x5d 0xc3 0xcc

我们再用VS反编译工具得到AddImplement函数的反编译代码,其效果如下图:


image.png


可以得到函数AddImplement的其实地址是0x00CE1210,同时,可以可以得到的其机器码:

0x55 0x8b 0xec 0x8b 0x45 0x08 0x03 0x45 0x0c 0x5d 0xc3 0xcc

从这个例子我们得出函数指针的本质:指向一个函数的指针,其保存的值就是函数的地址。


2. 调用C++私有函数实例


笔者觉得这个例子才是真正展现函数指针精华的例子,学习过C++或者Java的同学都知道,类声明的private函数或者变量,在类外部不能直接访问(排除friend的情况)。如果直接调用,由于开发语言的约定,直接在编译过程就会警报语法错误。那么,怎么达到这种效果呢,嘿嘿,使用函数指针吧,且看如下例子:


image.png


笔者建议童鞋们在实际工作中不要使用该方法进行代码编写和接口调用。


3. GetProcAddress实例


学习过C/C++系统编程(Windows或者Linux)的童鞋都知道,所谓的API编程,其实是基于系统接口或者第三方接口进行开发,通常这些接口都是没有源码,通过Windows上的DLL或者Uni*上的so提供函数功能。


下面例子讲述通过动态调用Windows的Kernerl32.DLL中的GetComputerNameW函数获取当前机器名的例子。


image.png

不过有童鞋有疑问,难道每次动态调用其它模块的接口都要这么操作或者函数指针吗?当然不是,一般开发过程中,一般开发都是直接引入第三方动态开发库,编译出来的二进制文件(PE文件或者ELF文件)的导入表中,系统的PE装载器会帮我们完成上述操作。

相关文章
|
3天前
|
搜索推荐 编译器 Linux
一个可用于企业开发及通用跨平台的Makefile文件
一款适用于企业级开发的通用跨平台Makefile,支持C/C++混合编译、多目标输出(可执行文件、静态/动态库)、Release/Debug版本管理。配置简洁,仅需修改带`MF_CONFIGURE_`前缀的变量,支持脚本化配置与子Makefile管理,具备完善日志、错误提示和跨平台兼容性,附详细文档与示例,便于学习与集成。
271 116
|
18天前
|
域名解析 人工智能
【实操攻略】手把手教学,免费领取.CN域名
即日起至2025年12月31日,购买万小智AI建站或云·企业官网,每单可免费领1个.CN域名首年!跟我了解领取攻略吧~
|
12天前
|
安全 Java Android开发
深度解析 Android 崩溃捕获原理及从崩溃到归因的闭环实践
崩溃堆栈全是 a.b.c?Native 错误查不到行号?本文详解 Android 崩溃采集全链路原理,教你如何把“天书”变“说明书”。RUM SDK 已支持一键接入。
663 219
|
5天前
|
数据采集 人工智能 自然语言处理
Meta SAM3开源:让图像分割,听懂你的话
Meta发布并开源SAM 3,首个支持文本或视觉提示的统一图像视频分割模型,可精准分割“红色条纹伞”等开放词汇概念,覆盖400万独特概念,性能达人类水平75%–80%,推动视觉分割新突破。
350 34
Meta SAM3开源:让图像分割,听懂你的话
|
10天前
|
人工智能 移动开发 自然语言处理
2025最新HTML静态网页制作工具推荐:10款免费在线生成器小白也能5分钟上手
晓猛团队精选2025年10款真正免费、无需编程的在线HTML建站工具,涵盖AI生成、拖拽编辑、设计稿转代码等多种类型,均支持浏览器直接使用、快速出图与文件导出,特别适合零基础用户快速搭建个人网站、落地页或企业官网。
1582 157
|
存储 人工智能 监控
从代码生成到自主决策:打造一个Coding驱动的“自我编程”Agent
本文介绍了一种基于LLM的“自我编程”Agent系统,通过代码驱动实现复杂逻辑。该Agent以Python为执行引擎,结合Py4j实现Java与Python交互,支持多工具调用、记忆分层与上下文工程,具备感知、认知、表达、自我评估等能力模块,目标是打造可进化的“1.5线”智能助手。
897 61
|
7天前
|
编解码 Linux 数据安全/隐私保护
教程分享免费视频压缩软件,免费视频压缩,视频压缩免费,附压缩方法及学习教程
教程分享免费视频压缩软件,免费视频压缩,视频压缩免费,附压缩方法及学习教程
295 140