C++指针解读(7)-- 指针和函数

news2025/1/19 20:27:09

前面我们讲过用指针变量作为函数参数。这里讲指向函数的指针变量和返回指针的函数。

1、指向函数的指针变量

跟变量一样,函数也会存储在内存空间中,函数的内存空间有一个起始地址,每次调用函数时就从该入口地址开始执行函数代码。

既然函数有地址,我们就可以定义一个指向该函数的指针变量。比如,我们可以定义这样的指针变量:

int (*pfun)();

从右往左读,先是(),表示这是一个函数;然后是(*pfun),表示一个指针指向这个函数;最后是void,表示这个函数返回int。

如果我们把指针的挂号去掉:

int *pfun();

则表示一个返回int*类型的函数。

所以,定义指向函数的指针变量的形式为:

(1)类型名 (*指针变量名)(函数参数列表)

(2)typedef 类型名 (*指针变量名)(函数参数列表)

这里必须注意,一个函数的指针变量只能指向定义时指定的类型的函数。比如int (*p)()表示函数指针变量p可以指向返回值是int的无参数函数。

2、函数指针的使用

我们来看一个使用函数指针的例子:

int max(int a, int b) {
    if (a > b) {
        return a;
    }
    else {
        return b;
    }
}

int main()
{
    int a = 3;
    int b = 7;

    int (*p)(int, int);
    p = max;
    int ret = p(3, 7);
    //也可以这么调用
    //int ret = (*p)(3, 7);
    printf(" max = %d\n", ret);

    return 0;
}

使用函数指针的注意事项:

(1)函数指针只能指向定义时指定的函数类型。比如int (*p)(int, int)就只能指向返回值是int,形参列表是2个int的函数。比如int max(int a, int b); int min(int a, int b)等这样的函数都可以。

(2)函数指针变量要调用哪个函数,就让指针指向哪个函数。

比如p = max,这里形参的列表是不用写的,只要写函数名就可以了。因为函数名代表函数的入口地址,让函数指针指向这个入口地址就可以了。

(3)用函数指针变量代替函数运行,比如p(a, b)。

(4)函数指针变量不能进行算术运算,p+n, p++等都是错误的。

3、用函数的指针作函数参数

指向函数的指针可以作为函数参数,把函数的指针作为形参,这样就能够在被调用函数中使用实参函数。

有下面几种传递函数指针的方式:

(1)显式地将形参定义为指向函数的指针

void func(int nValue,int (*pf)(int,int));

(2)第二个形参为函数类型,会自动转换为指向此类函数的指针

void func(int nValue,int pf(int,int));

(3)

typedef int (*PF)(int, int);

void func(int nValue, PF pf)

例子:

int add(int i, int j) {
    return i + j;
}

int sub(int i, int j) {
    return i - j;
}

typedef int (*pfun)(int i, int j);
int compute(pfun fun, int i, int j) {
    return fun(i, j);
}

int main()
{
    int a = 3;
    int b = 7;
    int (*pf1)(int i, int j);
    pf1 = sub;

    std::cout << compute(pf1, b, a) << std::endl;

    return 0;
}

4、函数指针数组

函数指针也可以存放在数组中。

假如有这么一个应用场景,系统需要根据输入的参数来选择需要执行的具体函数。

输入‘+’,则执行add()函数;输入‘-’,则执行sub()函数。

typedef int (*operation)(int i, int j);
operation ops[128] = { 0 };
ops['+'] = add;
ops['-'] = sub;

operation op1 = ops['+'];
printf(" 3 + 4 = %d\n", op1(3, 4));

operation op2 = ops['-'];
printf(" 7 - 3 = %d\n", op2(7, 3));

这里我们用'+', '-'作为数组的索引,因为char其实就是int类型,我们把数组长度定义为128,是因为ASCII共有128个字符,这样每个ASCII字符都能作为数组的索引存放。

5、返回指针值的函数

定义返回指针值的函数的形式为:

类型名 *函数名(参数列表)

返回指针时要注意这几种情况:

(1)如果返回的是函数内部局部变量的指针,那么这个指针出函数作用域时,其指向的对象已经失效。这种情况下就成了迷途指针或悬空指针。

int* invalidPointer() {
    int tmp = 3;

    return &tmp; //出函数后tmp对象已被释放,返回的指针成了: 迷途指针/悬空指针
}

(2)如果是在函数内部动态分配了内存的指针,记得在函数外部释放内存,避免产生内存泄漏。

int* localPointer() {
    int* pi = (int*)malloc(sizeof(int));
    return pi;
}

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

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

相关文章

Wordpress自定义小工具logo调用设置(可视化)

在主题开发中&#xff0c;需要调用网站的logo&#xff0c;最简单的办法就是用wp自带的函数&#xff0c;那就是the_custom_logo()&#xff0c;使用它还可以通过后台-自定义-logo&#xff0c;边修改边预览&#xff0c;还是很香的。 自定义徽标支持应首先使用add_theme_support()添…

【后端】韩顺平Java学习笔记(基础篇01)

因为之前有c基础&#xff0c;所以差不多一样的就简写了owo 来源&#xff1a;韩顺平 零基础30天学会Java 目录 I. 控制结构&#xff08;简&#xff09; 一、介绍 1. 顺序 → 从上到下执行&#xff0c;无跳转 2. 分支 → 单、双、多、嵌套 1&#xff09;单&#xff0c;即…

【GO入门】环境配置及Vscode配置

1 GO环境配置 欢迎来到Go的世界&#xff0c;让我们开始探索吧&#xff01; Go是一种新的语言&#xff0c;一种并发的、带垃圾回收的、快速编译的语言。它具有以下特点&#xff1a; 它可以在一台计算机上用几秒钟的时间编译一个大型的Go程序。Go为软件构造提供了一种模型&…

langchain callback学习

文章目录 一.quickstart二.Async callbacks三.把回调消息写入文件如何提取出来正则表达式官方的方法 一.quickstart 官方文档在此&#xff1a;https://python.langchain.com/docs/modules/callbacks/ 发现自己之前用langchain都是纯纯只是跑通&#xff0c;要能灵活使用还是得深…

freefilesync文件同步软件

下载 下载链接 https://freefilesync.org/download.php 往下拉&#xff0c;看到下载的链接 下载windows版本 下载地址&#xff1a; https://freefilesync.org/download/FreeFileSync_13.0_Windows_Setup.exe 直接复制到浏览器中访问就能下载 安装 双击安装包&#xff0c;一路默…

总结:JavaEE的Servlet中HttpServletRequest请求对象调用各种API方法结果示例

总结&#xff1a;JavaEE的Servlet中HttpServletRequest请求对象调用各种API方法结果示例 一方法调用顺序是按照英文字母顺序从A-Z二该示例可以用作servlet中request的API参考&#xff0c;从而知道该如何获取哪些路径参数等等三Servlet的API版本5.0.0、JSP的API版本&#xff1a;…

创建QDialog工程

创建QDialog工程 换掉图标 添加一个组件 水平布局 所有原件横向布局完成后&#xff0c;选中外框&#xff0c;点击Dialog,进行纵向布局 调整文本字体的大小 清空按钮的槽函数 下划线的槽函数 斜体的槽函数 加粗的槽函数 或者使用快剪辑&#xff1a;…

文心一言:文心大模型 4.0 即将发布

本心、输入输出、结果 文章目录 文心一言:文心大模型 4.0 即将发布前言文心 4.0 的成本问题架构文心 4.0 是否可以对标 GPT-4文心4.0 会不会收费弘扬爱国精神文心一言:文心大模型 4.0 即将发布 编辑:简简单单 Online zuozuo 地址:https://blog.csdn.net/qq_15071263 前言 …

【Java 进阶篇】JavaScript电灯开关案例:从原理到实现

JavaScript是一门强大的编程语言&#xff0c;它可以用来创建各种交互式网页应用。在这篇博客中&#xff0c;我们将通过一个简单的电灯开关案例来深入了解JavaScript的基础概念&#xff0c;包括HTML、CSS和JavaScript的结合使用。我们将从头开始构建这个案例&#xff0c;逐步引入…

Megatron-LM GPT 源码分析(一) Tensor Parallel分析

引用 本文基于开源代码 https://github.com/NVIDIA/Megatron-LM &#xff0c;通过GPT的模型运行示例&#xff0c;从三个维度 - 模型结构、代码运行、代码逻辑说明 对其源码做深入的分析。 Tensor Parallel源码分析

LabVIEW生产者消费者架构

LabVIEW生产者消费者架构 生产者/消费者模式可以轻松地同时处理多个进程&#xff0c;同时还能以不同速率迭代。 缓冲通信 当多个进程以不同速度运行时&#xff0c;就适合采用进程间缓冲通信。有了足够大的缓冲区后&#xff0c;生产者循环可以以快于消费者循环的速度运行&…

Java实现一个Redis可视化工具

https://github.com/tanhuang2016/RedisDesktopManagerFX https://gitee.com/hod_th/RedisDesktopManagerFX 老铁们,上面两个地址帮我点个star呢,谢谢 基本功能后面慢慢完善,有想法可以提需求哦 基本操作 string类型操作 list hash set zset类型操作

C++继承探究

文章目录 一、继承相关概念1、 基本概念2、继承方式3、如何构造基类4、基类和派生类对象赋值转换5、继承中的作用域 二、菱形继承的问题及解决方案三、虚继承的原理四、继承 VS 组合 一、继承相关概念 1、 基本概念 代码复用是编程语言设计的核心&#xff0c;对于一个函数&…

数学之-曼德勃罗

参考: 分形系统介绍以及代码实现 - 知乎 Java实现高分辨率曼德伯罗特集 - 知乎 Mandelbrot集的最新变化形态一览——MandelBox&#xff0c;Mandelbulb&#xff0c;Burning Ship&#xff0c;NebulaBrot-CSDN博客

VL53L5CX驱动开发(5)----运动阈值检测

VL53L5CX驱动开发----5.运动阈值检测 概述视频教学样品申请源码下载生成STM32CUBEMX选择MCU串口配置IIC配置 INT设置配置使能与复位X-CUBE-TOF1串口重定向代码配置检测流程TOF代码配置主程序演示结果 概述 本章目的是展示如何充分利用VL53L5CX传感器的高级特性&#xff0c;通过…

【LLM微调范式1】Prefix-Tuning: Optimizing Continuous Prompts for Generation

论文标题&#xff1a;Prefix-Tuning: Optimizing Continuous Prompts for Generation 论文作者&#xff1a;Xiang Lisa Li, Percy Liang 论文原文&#xff1a;https://arxiv.org/abs/2101.00190 论文出处&#xff1a;ACL 2021 论文被引&#xff1a;1588&#xff08;2023/10/14&…

C# 图解教程 第5版 —— 第6章 方法

文章目录 6.1 方法的结构6.2 方法体内部的代码执行6.3 局部变量6.3.1 类型推断和 var 关键字6.3.2 嵌套块中的局部变量 6.4 局部常量6.5 控制流6.6 方法调用&#xff08;*&#xff09;6.7 返回值&#xff08;*&#xff09;6.8 返回语句和 void 方法6.9 局部函数6.10 参数&#…

关于数据链路层(初步)

以太网帧格式&#xff1a; 源地址和目的地址是指网卡的硬件地址&#xff08;也叫MAC地址&#xff09;&#xff0c;长度是48位&#xff0c;是在网卡出厂时固 化的&#xff1b; 帧协议类型字段有三种值&#xff0c;分别对应载荷的形式&#xff0c;有IP、ARP、RARP&#xff1b; …

Go-Python-Java-C-LeetCode高分解法-第十周合集

前言 本题解Go语言部分基于 LeetCode-Go 其他部分基于本人实践学习 个人题解GitHub连接&#xff1a;LeetCode-Go-Python-Java-C 欢迎订阅CSDN专栏&#xff0c;每日一题&#xff0c;和博主一起进步 LeetCode专栏 我搜集到了50道精选题&#xff0c;适合速成概览大部分常用算法 突…

LuaJit交叉编译移植到ARM Linux

简述 Lua与LuaJit的主要区别在于LuaJIT是基于JIT&#xff08;Just-In-Time&#xff09;技术开发的&#xff0c;可以实现动态编译和执行代码&#xff0c;从而提高了程序的运行效率。而Lua是基于解释器技术开发的&#xff0c;不能像LuaJIT那样进行代码的即时编译和执行。因此&…