Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >函数指针和指针函数用法和区别

函数指针和指针函数用法和区别

作者头像
全栈程序员站长
发布于 2022-06-25 06:06:39
发布于 2022-06-25 06:06:39
23400
代码可运行
举报
运行总次数:0
代码可运行

大家好,又见面了,我是你们的朋友全栈君。

前言

函数指针和指针函数,在学习 C 语言的时候遇到这两个东西简直头疼,当然还有更头疼的,比如什么函数指针函数、指针函数指针、数组指针、指针数组、函数指针数组等等,描述越长其定义就越复杂,当然理解起来就越难,特别是刚开始学习这门语言的童鞋,估计碰到这些东西就已经要崩溃了,然后好不容易死记硬背下来应付考试或者面试,然后过了几天发现,又是根本不会用,也不知道该在哪些地方用,这就尴尬了。 今天这里只讲两个相对简单的,其实上面说那些太复杂的东西也真的很少用,即便是用了理解起来很麻烦,所以莫不如先深刻理解这两个比较容易的,并且项目中比较常用到。

正文

先来看看两者的定义以及说明。

指针函数

定义

指针函数,简单的来说,就是一个返回指针的函数,其本质是一个函数,而该函数的返回值是一个指针。 声明格式为:*类型标识符 函数名(参数表)

这似乎并不难理解,再进一步描述一下。 看看下面这个函数声明:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int fun(int x,int y);

这种函数应该都很熟悉,其实就是一个函数,然后返回值是一个 int 类型,是一个数值。 接着看下面这个函数声明:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int *fun(int x,int y);

这和上面那个函数唯一的区别就是在函数名前面多了一个*号,而这个函数就是一个指针函数。其返回值是一个 int 类型的指针,是一个地址。

这样描述应该很容易理解了,所谓的指针函数也没什么特别的,和普通函数对比不过就是其返回了一个指针(即地址值)而已。

指针函数的写法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int *fun(int x,int y);
int * fun(int x,int y);
int* fun(int x,int y);

这个写法看个人习惯,其实如果*靠近返回值类型的话可能更容易理解其定义。

示例

(由于本人习惯于 Qt 中进行开发,所以这里为了方便,示例是在 Qt 工程中写的,其语法是一样的,只是输出方式不同) 来看一个非常简单的示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
typedef struct _Data{
    int a;
    int b;
}Data;

//指针函数
Data* f(int a,int b){
    Data * data = new Data;
    data->a = a;
    data->b = b;
    return data;
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //调用指针函数
    Data * myData = f(4,5);
    qDebug() << "f(4,5) = " << myData->a << myData->b;

    return a.exec();
}

输出如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
f(4,5) =  4 5

注意:在调用指针函数时,需要一个同类型的指针来接收其函数的返回值。 不过也可以将其返回值定义为 void*类型,在调用的时候强制转换返回值为自己想要的类型,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//指针函数
void* f(int a,int b){
    Data * data = new Data;
    data->a = a;
    data->b = b;
    return data;
}

调用:
Data * myData = static_cast<Data*>(f(4,5));

其输出结果是一样的,不过不建议这么使用,因为强制转换可能会带来风险。

函数指针

定义

函数指针,其本质是一个指针变量,该指针指向这个函数。总结来说,函数指针就是指向函数的指针。 声明格式:类型说明符 (*函数名) (参数) 如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int (*fun)(int x,int y);

函数指针是需要把一个函数的地址赋值给它,有两种写法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
fun = &Function;
fun = Function;

取地址运算符&不是必需的,因为一个函数标识符就表示了它的地址,如果是函数调用,还必须包含一个圆括号括起来的参数表。

调用函数指针的方式也有两种:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
x = (*fun)();
x = fun();

两种方式均可,其中第二种看上去和普通的函数调用没啥区别,如果可以的话,建议使用第一种,因为可以清楚的指明这是通过指针的方式来调用函数。当然,也要看个人习惯,如果理解其定义,随便怎么用都行啦。

示例

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int add(int x,int y){
    return x+y;
}
int sub(int x,int y){
    return x-y;
}
//函数指针
int (*fun)(int x,int y);

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //第一种写法
    fun = add;
    qDebug() << "(*fun)(1,2) = " << (*fun)(1,2) ;
	//第二种写法
    fun = &sub;
    qDebug() << "(*fun)(5,3) = " << (*fun)(5,3)  << fun(5,3)return a.exec();
}

输出如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(*fun)(1,2) =  3
(*fun)(5,2) =  2 2

上面说到的几种赋值和调用方式我都分别使用了,其输出结果是一样的。

二者区别

通过以上的介绍,应该都能清楚的理解其二者的定义。那么简单的总结下二者的区别:

定义不同

指针函数本质是一个函数,其返回值为指针。 函数指针本质是一个指针,其指向一个函数。

写法不同

指针函数:int* fun(int x,int y); 函数指针:int (*fun)(int x,int y); 可以简单粗暴的理解为,指针函数的*是属于数据类型的,而函数指针的星号是属于函数名的。 再简单一点,可以这样辨别两者:函数名带括号的就是函数指针,否则就是指针函数。

用法不同

上面已经写了详细示例,这里就不在啰嗦了。

总而言之,这两个东西很容易搞混淆,一定要深入理解其两者定义和区别,避免犯错。

另外,本文都是针对普通函数指针进行介绍,如果是C++非静态成员函数指针,其用法会有一些区别,在另外一篇博客中单独介绍,文章在这里

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/152159.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
mybatis常用标签,详细总结
if标签通常用于WHERE语句、UPDATE语句、INSERT语句中,通过判断参数值来决定是否使用某个查询条件、判断是否更新某一个字段、判断是否插入某个字段的值。
Java编程指南
2019/10/30
2.2K0
mybatis常用标签,详细总结
【MyBatis-2】MyBatis之xml 配置版
MyBatis 是一款标准的 ORM 框架,被广泛的应用于各企业开发中。MyBatis 支持普通的 SQL 查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以及对结果集的检索封装。MaBatis 可以使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的 POJO(Plain Old Java Objects,普通的 Java 对象)映射成数据库中的记录。
云深i不知处
2020/09/16
5330
MyBatis动态SQL(认真看看, 以后写SQL就爽多了)
MyBatis 令人喜欢的一大特性就是动态 SQL。 在使用 JDBC 的过程中, 根据条件进行 SQL 的拼接是很麻烦且很容易出错的。 MyBatis 动态 SQL 的出现, 解决了这个麻烦。
用户1093975
2019/03/08
1.9K1
你真的会写mybatis.xml吗?养成好习惯写养眼好用的xml
我们使用mybatis无非就是进行一些增删改查的操作,但是简单的增删改查想要写好却大有门道。
我的小熊不见了丶
2019/05/23
1.3K0
MyBatis动态SQL
传统的使用JDBC的方法,相信大家在组合复杂的的SQL语句的时候,需要去拼接,稍不注意哪怕少了个空格,都会导致错误。MyBatis的动态SQL功能正是为了解决这种问题, 其通过 if、choose、when、otherwise、trim、where、set、foreach和bind等9种标签,可组合成非常灵活的SQL语句,从而提高开发人员的效率。
用户10358987
2024/04/23
1720
别再手动拼接 SQL 了,MyBatis 动态 SQL 写法应有尽有,建议收藏!
动态 SQL 是 MyBatis 的强大特性之一。在 JDBC 或其它类似的框架中,开发人员通常需要手动拼接 SQL 语句。根据不同的条件拼接 SQL 语句是一件极其痛苦的工作。
程序员蜗牛
2024/03/16
1.7K1
别再手动拼接 SQL 了,MyBatis 动态 SQL 写法应有尽有,建议收藏!
Mybatis编程式开发实战
1.API方式 SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。 如下面代码块中的com.gupaoedu.mapper.BlogMapper.selectBlogById
名字是乱打的
2021/12/22
3260
Mybatis编程式开发实战
MyBatis 源码学习笔记(二)- MyBatis 进阶(Part A)
将MyBatis 源码学习笔记(一)- MyBatis概述中创建的mybatis-quick-start工程拷贝并重命名为mybatis-intermediate。
RiemannHypothesis
2022/08/19
1.3K0
MyBatis 源码学习笔记(二)- MyBatis 进阶(Part A)
Maven搭建SpringMVC+Mybatis项目详解
最近比较闲,复习搭建一下项目,这次主要使用spring+SpringMVC+Mybatis。项目持久层使用Mybatis3,控制层使用SpringMVC4.1,使用Spring4.1管理控制器,数据库连接池使用druid数据源,该项数据库暂使用MySQL。(如果是Oracle需修改pom.xml)
yaohong
2019/09/11
6550
数据层框架应用--Mybatis(一) 基于XML映射文件实现数据的CRUD
SqlSessionFactory是MyBatis框架中十分重要的对象,它是单个数据库映射关系经过编译后的内存镜像,其主要作用是创建SqlSession。
lomtom
2021/10/27
9250
数据层框架应用--Mybatis(一) 基于XML映射文件实现数据的CRUD
Java从入门到精通二十一(Mybatis框架)
框架就是一个软件的半成品,许多实现的细节都已经实现。主要的功能就是可以帮助我们减少繁琐重复的操作。 Mybatis就是用来简化JDBC的开发,简化一些繁琐的操作。
兰舟千帆
2022/07/16
4670
Java从入门到精通二十一(Mybatis框架)
mybatis 使用经验小结
一、多数据源问题 主要思路是把dataSource、sqlSesstionFactory、MapperScannerConfigurer在配置中区分开,各Mapper对应的包名、类名区分开 1 <?
菩提树下的杨过
2018/01/19
1.1K0
mybatis 使用经验小结
【Mybatis】探秘 Mybatis:解锁数据库增删查改的密码,驱动数据变革新征程
第一步:首先新建一个Mapper类的包,主要用于存放这里的mapper接口,是 Mybatis 进行数据库操作的关键环节,是Mybatis对于数据库操作的重要一环,对应这对数据库的CRUD;
用户11288949
2025/01/17
1250
【Mybatis】探秘 Mybatis:解锁数据库增删查改的密码,驱动数据变革新征程
SpringBoot入门建站全系列(十九)集成Activiti做工作流
Activiti作为一个流行的开源工作流引擎,正在不断发展,其6.0版本以API形式提供服务,而之前版本基本都是要求我们的应用以JDK方式与其交互,只能将其携带到我们的应用中,而API方式则可以服务器独立运行方式,能够形成一个专网内工作流引擎资源共享的方式。
品茗IT
2019/08/23
1.3K0
深入理解MyBatis XML配置文件:必需部分与可选部分详解
MyBatis 是一个流行的持久层框架,通过 XML 映射文件定义 SQL 语句和映射规则,简化了 Java 应用程序与数据库的交互。本文将深入探讨 MyBatis 中 XML 配置文件的用法,特别是那些部分必须有值,哪些部分可以省略。
九转成圣
2024/08/05
6260
Mybatis传参的方式总结
本文总结了MyBatis中传参的多种方式,包括基本类型参数、对象参数、Map参数、注解参数等。通过了解这些传参方式,读者可以更好地在MyBatis中进行参数的传递与处理。
猫头虎
2024/04/07
6570
Mybatis常用操作
if标签通常用于WHERE语句、UPDATE语句、INSERT语句中,通过判断参数值来决定是否使用某个查询条件、判断是否更新某一个字段、判断是否插入某个字段的值。
啵啵肠
2023/11/20
1670
mybatis 开发自定义插件,你学废了吗
MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。比如执行前、执行后或者对SQL结果集处理、sql入参处理等,这样就可以在不修改mybatis源码的情况下对sql执行的过程或结果进行修改,实现了解耦。
索码理
2022/09/20
5700
mybatis 开发自定义插件,你学废了吗
从架构角度看MyBatis及foreach用法小结
关注点分离[Separation of Concerns,简称SOC]是最经典的架构设计原则之一,在许多架构设计中被广泛使用。 关注点分离原则为我们的架构设计提出了三点要求。
烟雨平生
2023/03/07
1.3K0
从架构角度看MyBatis及foreach用法小结
MyBatis 源码学习笔记(二)- MyBatis 进阶(Part B)
resultMap 是MyBatis中最重要最强大的标签,它可以让你从90%的JDBC ResultSets代码中解脱,对复杂语句进行联合映射时,会非常方便
RiemannHypothesis
2022/08/19
9150
MyBatis 源码学习笔记(二)- MyBatis 进阶(Part B)
推荐阅读
相关推荐
mybatis常用标签,详细总结
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验