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

C/C++函数指针与指针函数

原创
作者头像
C语言与CPP编程
修改于 2020-10-26 02:47:32
修改于 2020-10-26 02:47:32
2.7K00
代码可运行
举报
文章被收录于专栏:c语言与cpp编程c语言与cpp编程
运行总次数:0
代码可运行

来源:公众号(c语言与cpp编程)

关于指针,前面文章C语言指针详解有过介绍,这里主要讨论函数指针和指针函数。

1 什么是指针?

定义:指针是程序数据在内存中的地址,而指针变量是用来保存这些地址的变量;

上面一个 4GB 的内存可以存放 2^32 字节的数据。左侧连续的十六进制编号就是内存地址,每个内存地址对应一个字节的内存空间。而指针变量保存的就是这个编号,也即内存地址。

指针的声明:

指针其实就是一个变量,指针的声明方式与一般的变量声明类似,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int *p;         // 声明一个 int 类型的指针 p,该指针指向一个int类型的对象
char *p         // 声明一个 char 类型的指针 p,该指针指向一个int类型的对象
int *arr[10]    // 声明一个指针数组,该数组有10个元素,其中每个元素都是一个指向 int 类型对象的指针
int (*arr)[10]  // 声明一个数组指针,该指针指向一个 int 类型的一维数组
int **p;        // 声明一个指针 p ,该指针指向一个 int 类型的指针

声明一个指针变量并不会自动分配任何内存。在对指针进行间接访问之前,指针必须进行初始化:或是使他指向现有的内存,或者给他动态分配内存,否则我们并不知道指针指向哪儿,这个问题需要特别关注。

2 什么是函数指针?

函数指针定义:函数指针是指向函数的指针变量。因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。

其通用表达式为:类型说明符 (*函数名) (参数)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int (*fun)(int x)  //函数指针的定义
int (*fun)(int x,int y) //函数指针的定义

函数指针在PC软件开发中使用较少,在嵌入式行业使用较多,但是无论是PC软件还是嵌入式软件,理解函数指针的定义和使用,对于理解程序设计都是很有好处的。

函数指针的赋值

函数指针和其他指针一样定义之后使用之前也是需要初始化。

函数指针有两个用途:调用函数做函数的参数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int (*fun)(int x,int y) //函数指针的定义
fun = &Function          //函数指针的赋值方式1
fun = Function           //函数指针的赋值方式2
x = (*fun)()             //函数指针的调用方式1
x = fun()                //函数指针的调用方式2

函数赋值的时候取地址运算符&不是必需的,因为一个函数标识符就表示了它的地址,并且赋值的时候函数不需要带圆括号;

如果是函数调用,还必须包含一个圆括号括起来的参数表。

函数指针的用法

我们使用指针的时候,需要通过钥匙 * 来取其指向的内存里面的值,函数指针使用也如此。通过用(*pf)取出存在这个地址上的函数,然后调用它。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
char*  fun(char* p1,char* p2)
{
  int i = 0;
  i = strcmp(p1,p2);
  if(0 == i)
  {
    return p1;
  }
  else
  {
     return p2;
  }
}
int main()
{
  char * (*pf)(char* p1,char* p2);
  pf = &fun;
  (*pf)("aa","bb");
  return 0;
}

这里需要注意到是,在Visual C++6.0里,给函数指针赋值时,可以用&fun或直接用函数名fun。这是因为函数名被编译之后其实就是一个地址,所以这里两种用法没有本质的差别。

用法延申

当我们不满足于函数指针上面如此简单的用法时,这时候需要一个高级用法来扩展我们对于函数指针的认知边界。

感兴趣的同学可以看看下面这个用法,并尝试理解该表达式是如何使用的函数指针。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(* (void(*)()) 0)(); //出自《C Trap and Pitfalls》这本经典的书

答案如下:   ``

  • 第一步:通过 void(*) (),可以明白这是一个函数指针类型。这个函数没有参数,没有返回值。
  • 第二步:通过 (void(*) ())0,可以明白这是将 0强制转换为函数指针类型, 0是一个地址,也就是说一个函数存在首地址为 0的一段区域内。
  • 第三步:通过 (*(void(*) ())0),可以明白这是取0地址开始的一段内存里面的内容。
  • 第四步:最终理解 (*(void(*) ())0)(),这是函数调用。

让程序跳转到绝对地址为0x0113F90C

方法一:

  • 0x0113F90C地址强制转换为函数指针类型,即: (void (*)())0x0113F90C
  • 然后调用: ((void (*)())0x0113F90C)()

方法二:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
typedef (void (*)())  VoidFuncPtr;
((VoidFuncPtr)0x0113F90C)();

面试题:指出程序的错误

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<stdio.h>

void main(void)
{
   int max(x,y);
   int *p=max;
   int a,b,c,d;
   scanf("%d %d %d",a,b,c);
   d=p(p(a,b),c);
   printf("d:%d\n",d);
   return;
}
int max(int a,int y)
{
   return(x > y ?x:y);
}

答案

  • int max(x ,y);函数声明错误,改为: int max(int x,int y);

解析:max函数声明只是写出了函数的形参的名称,这对参数的类型来说是毫无意义的,编译器会把xy当做数据类型来看,编译时会出错,max的调用肯定也会出错。

  • int *p=max;指针定义错误,改为: int (*p)(int ,int)=max;

解析:函数的指针是不能直接赋值给int型指针.

  • scanf("%d %d %d",a,b,c);库函数使用错误,改为 scanf("%d %d%d",&a,&b,&c);

解析:库函数使用错误,第二部分应该是接收数据的地址,这里却写成了变量。

  • d=p(p(a,b),c);函数指针调用函数错误,改为 d=(*p)((*p)(a,b),c);`

解析:用函数指针调用函数的格式如下:(【*】【函数指针名称】)(【参数列表】);不能直接用函数指针加上参数就直接调用

3 什么是指针函数?

指针函数定义:指针函数的落脚点是一个函数,这个函数的返回值是一个指针,与普通函数int function(int,int)类似,只是返回的数据类型不一样而已。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
_type_ *function(int, int) //返回的是指针地址
int function(int,int)     //返回的是int型数据。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int  *fun(int x)        //指针函数的定义
int * fun(int x,int y)  //指针函数的定义
int* fun(int x,int y)   //指针函数的定义

以上三种写法均正确,但是*靠近返回值一点更容易理解。

指针函数的调用

在调用指针函数时,需要一个同类型的指针来接收其函数的返回值。

代码语言: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();
}

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

其输出结果是一样的,不过不建议这么使用,因为强制转换可能会带来风险。返回类型可以是任何基本类型和复合类型。返回指针的函数的用途十分广泛。

事实上,每一个函数,即使它不带有返回某种类型的指针,它本身都有一个入口地址,该地址相当于一个指针。

比如函数返回一个整型值,实际上也相当于返回一个指针变量的值,不过这时的变量是函数本身而已,而整个函数相当于一个“变量”。

4 函数指针与指针函数区别

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

1. 定义不同

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

2. 写法不同

  • 指针函数: int* fun(int x,int y);
  • 函数指针: int (*fun)(int x,int y);

可以简单粗暴的理解为,指针函数的*是属于数据类型的,而函数指针的星号是属于函数名的。

再简单一点,可以这样辨别两者:函数名带括号的就是函数指针,否则就是指针函数。

3. 用法不同

上面函数指针和指针函数的用法都有,但是函数指针的用法会更多,相对而言难度也更大,例如函数指针与回调函数,如果是C++非静态成员函数指针,其用法也会有一些区别,感兴趣的同学可以关注后续推文或自行查阅相关书籍。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
指针函数和函数指针(附实例详解)
指针函数与函数指针表示方法的不同,千万不要混淆。最简单的辨别方式就是看函数名前面的指针*号有没有被括号()包含,如果被包含就是函数指针,反之则是指针函数。
全栈程序员站长
2022/06/25
3.7K0
指针函数和函数指针(附实例详解)
一看就会的C语言笔记——指针函数、函数指针、回调函数
//函数返回值必须用同类型的变量来接受,也就是说,指针函数的返回值必须赋值给同类型的指针变量。
诸葛青云
2018/09/22
2.6K0
一看就会的C语言笔记——指针函数、函数指针、回调函数
C语言 函数指针和指针函数及Main()函数
指针函数 定义 指针函数,简单的来说,就是一个返回指针的函数,其本质是一个函数,而该函数的返回值是一个指针。 声明格式为:类型标识符 *函数名(参数表)
全栈程序员站长
2022/06/25
7910
C语言 函数指针和指针函数及Main()函数
c++指针函数的使用——回调函数
1 /* 2 3 函数指针 4 5 函数也是有地址的 6 7 所谓函数指针,就是指向函数的指针,函数指针也是一个变量,可以指向不同的函数。同时通过函数指针可以调用其指向函数,从而使函数的调用更加灵活。 8 9 函数指针的用途 10 11 12 13 14 */ 15 16 #include<iostream> 17 using namespace std; 18 int add(int x, int y); 19 int add(int x, in
拾点阳光
2018/05/10
2K0
详解C语言指针函数、函数指针、函数指针数组「建议收藏」
指针函数就是返回指针值的函数,本质是一个函数。所以指针函数等价于“返回值为指针的函数”。
全栈程序员站长
2022/06/25
2.2K0
【C语言笔记】指针函数与函数指针?
由于“*”的优先级低于“()”的优先级,因而pfun首先和后面的“()”结合,也就意味着,pfun是一个函数。即:int *(pfun(int, int));
正念君
2019/06/26
1.5K0
【C语言笔记】指针函数与函数指针?
C语言指针函数和函数指针区别
C和C++中经常会用到指针,和数据项一样,函数也是有地址的,函数的地址是存储其机器语言代码的内存的开始地址。
全栈程序员站长
2022/06/25
8770
【C/C++教学】浅谈指针函数和函数指针
在小编被指针函数和函数指针苦苦折磨了long time之后,灵感突发,在查阅相关资料和总结自己的学习心得之时写了此文,有不足之处请多多指出!
短短的路走走停停
2019/05/14
4440
C语言指针做函数参数,指针做函数返回类型
有时候我们可以使用函数的返回值来回传数据,在简单的情况下是可以的,但是如果返回值有其它用途(例如返回函数的执行状态量),或者要回传的数据不止一个,返回值就解决不了了,所以要引用上指针来传递。
C语言中文社区
2022/11/08
2.9K0
C语言指针做函数参数,指针做函数返回类型
c语言函数指针的理解与使用
C)这很容易,fun3是函数名,p1,p2是参数,其类型为char *型,函数的返回值为char *类型。 B) 也很简单,与C)表达式相比,唯一不同的就是函数的返回值类型为char**,是个二级指针。 A) fun1是函数名吗?回忆一下前面讲解数组指针时的情形。我们说数组指针这么定义或许更清晰:
用户7678152
2020/08/19
1.1K0
指针函数和函数指针「建议收藏」
指针函数和函数指针是C语言里两个比较绕的概念。但是不仅面试题爱考,实际应用中也比较广泛。很多人因为搞不清这两个概念,干脆就避而远之,我刚接触C语言的时候对这两个概念也比较模糊,特别是当指针函数、函数指针、函数指针变量、函数指针数组放在一块的时候,能把强迫症的人活活逼疯。 其实如果理解了这些概念的本质,是不需要死记硬背的,理解起来也比较容易。
全栈程序员站长
2022/06/25
5750
指针函数和函数指针「建议收藏」
C++学习笔记 -- 函数指针与指针函数
函数指针:指向函数的指针,首先它是指针变量(同指向一个整形变量、字符、数组一样),其次它指向一个函数(地址)。
meteoric
2018/11/16
8210
函数指针和指针函数的学习小结
函数指针是指向函数的指针,指针函数是指一个函数的返回值是一个指针,但下面的几道题还是感觉很迷惑。各位能否讲的详细点呢?
阳光岛主
2019/02/19
1.2K0
【编程基础】C语言指针函数和函数指针
往往,我们一提到指针函数和函数指针的时候,就有很多人弄不懂。下面详细为大家介绍C语言中指针函数和函数指针。 一、指针函数 当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需要指针或地址的表达式中。 格式: 类型说明符 * 函数名(参数) 当然了,由于返回的是一个地址,所以类型说明符一般都是int。 例如: int *GetDate(); int * aaa(int,int); 函数返回的是一个地址值,经常使用在返回数组的某一元素地址上。 int * GetDate(int
程序员互动联盟
2018/03/12
2.2K0
【C/C++笔记】:易错难点1
A 2^126-2^103 B 2^127-2^104 C 2^127-2^103 D 2^128-2^104
IsLand1314
2024/10/15
1020
【C/C++笔记】:易错难点1
C语言学习——指针精华(2)
char *cp; 与 char str[20]; 的区别 str由若干元素组成,每个元素放一个字符;而cp中存放字符串首地址 赋值方式: 字符数组只能对元素赋值。 char str[20]; str=“I love China!”; () 字符指针变量可以用: char *cp; cp=“I love China!”; () 赋初值:char *cp=“China!”; 等价 char *cp; cp=“China!”; char str[14]={“China”};不等价char str[14]; str[ ]=“China” ()
全栈程序员站长
2022/09/23
3330
C语言学习——指针精华(2)
函数指针的定义方式,和指针函数的区别,函数指针数组
可以类比数组指针:int(*p)[10] 方式1: #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> void fun1(int a, int b) { printf("%d+%d", a, b); } void test() { //函数指针定义的三种方式 //1.先定义出函数类型,再通过函数类型定义指针变量 typedef void(FUNC_TYPE)(int, int); FUNC_TYPE* func = fun1; func(10,2
大忽悠爱学习
2021/03/02
1.4K0
函数指针的定义方式,和指针函数的区别,函数指针数组
函数指针
前言: 先看两个基础,函数指针和extern关键字,然后由一个具体的例子,具体使用下函数指针。 一、基础 函数指针:即指向函数的指针,本质还是一个指针。 函数指针的声明:返回值类型 ( * 指针变量名
用户1215536
2018/02/05
1.1K0
函数指针,指针函数,返回值为指针的函数「建议收藏」
在学习C语言时,一个比较容易混淆的概念就是函数指针、指针函数、返回值为指针的函数。本文将对这三个概念进行区分。指针函数就是返回值为指针的函数,两个本质上是同一事物,只是叫法不同。函数指针就是一个指向函数的指针,本质上是一个指针,只是这个指针指向的对象是函数,而不是一般意义上的存储对象。
全栈程序员站长
2022/06/25
3.3K0
C语言中函数指针和回调函数的详解
函数指针:指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。函数指针有两个用途:调用函数和做函数的参数。
全栈程序员站长
2022/06/25
8930
C语言中函数指针和回调函数的详解
相关推荐
指针函数和函数指针(附实例详解)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验