大话 函数指针 和 指针函数
一:起因
(1)指针函数是指带指针的函数,即本质是一个函数。函数返回类型是某一类型的指针,即我们常见的函数类型,且返回值是指针。
(2)函数指针是指向函数的指针变量,即本质是一个指针变量,是一个指向函数(可能是代码区)的首地址的指针,正如我们都知道,数组名就是指向数组第一个元素的常量指针(详见《数组拾遗》)。同理,对于一个函数而言,函数名也是指向函数第一条指令的常量指针。而编译器要做的就是在程序编译之后,为每个函数分配一个首地址,即该函数第一条指令的地址。一般情况下,我们可以用一个指针来保存这个地址,而这个指针就是函数指针,该指针可以看作是它指向函数的别名,所以我们可以用该指针来调用这个函数。
(3)对指针的应用是C语言编程的精髓所在,而回调函数就是C语言里面对函数指针的高级应用。简而言之,回调函数是一个通过函数指针调用的函数。如果你把函数指针(函数的入口地址)传递给另一个函数,当这个函数指针被用来调用它所指向的函数时,我们就说这个函数是回调函数。
(4)我们非常熟悉的,而且经常用到的可能就是sort(begin,end)函数和 sort(begin,end,cmp);其中cmp正事函数名(即像数组名一样代表函数的首地址):
bool cmp(void const *a,void const *b)
{return *((int *)a) > *((int *)b);
}
注意强制类型转换,比较函数的参数必须被声明为void *以匹配查找函数的原型,然后强制转换为(int *)类型用于比较整型。然后把一个指向这个函数的指针作为参数传递给查找函数,查找函数调用这个比较函数来执行比较,采用这个方法,任何类型的值得都可以进行比较。
(5)注意指针函数与函数指针表示方法的不同,千万不要混淆。最简单的辨别方式就是看函数名前面的指针*号有没有被括号()包含,如果被包含就是函数指针,反之则是指针函数。
二:详细分析
(1)指针函数是指带指针的函数,即本质是一个函数。函数返回类型是某一类型的指针
类型标识符 *函数名(参数表)
int *f(x,y);
首先它是一个函数,只不过这个函数的返回值是一个地址值。函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量。例如:
float *fun();
float *p;
p = fun(a);
(2)函数指针是指向函数的指针变量,即本质是一个指针变量。
int (*f) (int x); /* 声明一个函数指针 */
f=func; /* 将func函数的首地址赋给指针f */
其实这里不能称为函数名,应该叫做指针的变量名。这个特殊的指针指向一个返回整型值的函数。指针的声明笔削和它指向函数的声明保持一致。
指针名和指针运算符外面的括号改变了默认的运算符优先级。如果没有圆括号,就变成了一个返回整型指针的函数的原型声明。例如:
void (*fptr)();
把函数的地址赋值给函数指针,可以采用下面两种形式:
fptr=&Function;
fptr=Function; // 建议用这种方式
取地址运算符&不是必需的,因为单单一个函数标识符就标号表示了它的地址,如果是函数调用,还必须包含一个圆括号括起来的参数表。
可以采用如下两种方式来通过指针调用函数:
x=(*fptr)();
x=fptr();// 建议用这种方式
(3)易混淆的地方:
函数指针的定义:
type (*func)(type&,type &) 或者 type (*func)(type ,type)
该语句声明了一个指针func,它指向了一个函数,这个函数带有了2个type型参数并返回一个type的值。(p.s. type类型可以被看成是int或者是floast等C++的类型)。
A:一个指向函数的指针必须确保该函数被定义且分配了内存,否则它将指向一个空地址,这个可是大忌!
B: 特别注意第一个括号的位置。如果我们不写括号,如下:
type *func(type ,type)
这就不是一个指向函数的指针了,而是声明了一个函数,该函数返回一个type类型的指针
有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的.函数指针有两个用途:调用函数和做函数的参数。
( 4 ) 注意指针函数与函数指针表示方法的不同,千万不要混淆。最简单的辨别方式就是看函数名前面的指针 * 号有没有被括号()包含,如果被包含就是函数指针,反之则是指针函数。
三:函数指针的高级应用---- 作为函数的参数
(1)下面程序中,给出了三种不同类型的函数指针,分别用(1)(2)(3)做了标注区分;分为声明部分,实现部分,调用部分。
(2)代码
#include <iostream>
using namespace std;void my_swap(int &,int &);// (4)普通函数的声明
int my_min(int,int);// (5)普通函数的声明
void my_input(void (*func)(int &,int &));//(1) 带有函数指针参数的声明
void my_input(int (*func)(int,int));// (2)带有函数指针参数的声明
void my_print(int,int,int (*func)(int,int));// (3)带有函数指针参数的声明
int main()
{cout << "please input two numbers:" << endl;my_input(my_swap);//(1) 带有函数指针参数的调用,函数名即为函数代码区的首地址my_input(my_min);// (2)带有函数指针参数的调用,函数名即为函数代码区的首地址int a,b;cin >> a >> b;my_print(a,b,my_min);// (3)带有函数指针参数的调用,函数名即为函数代码区的首地址return 0;
}
void my_input(void (*func)(int &,int&))// (1)带有函数指针参数的实现
{int a,b;cin >> a >> b;func(a,b);// 指针指向的函数代码区的首地址cout << a << ",,," << b << endl;
}
void my_input(int (*func)(int,int))// (2)带有函数指针参数的实现
{int a,b;cin >> a >> b;int mi = func(a,b);// 指针指向的函数代码区的首地址cout << "a,,,b:" << mi << endl;
}
void my_print(int a,int b,int (*func)(int,int))// (3)带有函数指针参数的实现
{int mi = func(a,b);// 指针指向的函数代码区的首地址cout << a << ",," << b << ",," << mi << endl;
}
int my_min(int a,int b)// (5)
{return a<b?a:b;
}
void my_swap(int &a,int &b)// (4)
{a ^= b;b ^= a;a ^= b;
}
大话 函数指针 和 指针函数相关推荐
- c/c++中的函数指针和指针函数
定义 1.指针函数,本质是函数,返回值为指针,形如,int *pfun(int, int),由于"*"的优先级低于"()"的优先级,所以等同于int *(pfu ...
- C++ 笔记(14)— 指针(指针声明、取地址、取值、new/delete、NULL指针、指针运算、指针数组、数组指针、指针传递给函数、从函数返回指针)
1. 声明指针 指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址.就像其他变量或常量一样,您必须在使用指 针存储其他变量地址之前,对其进行声明. 指针变量声明的一般形式为: type * ...
- Go 学习笔记(13)— 指针定义、指针特点、空指针、指针数组、指向指针的指针、指针作为函数入参
1. 复合数据类型 Go 语言基本的复合数据类型有指针.数组.切片.字典.通道.结构和接口等.格式如下: * pointerType // 指针类型, [n]elementType // 数组类型, ...
- C指针6:指针变量作为函数参数
在C语言中,函数的参数不仅可以是整数.小数.字符等具体的数据,还可以是指向它们的指针.用指针变量作函数参数可以将函数外部的地址传递到函数内部,使得在函数内部可以操作函数外部的数据,并且这些数据不会随着 ...
- C++成员变量指针和成员函数指针【The semantics of funcitons】
原文:https://blog.csdn.net/laojiu_/article/details/68946915 (原文有笔误) 1. #include <cstdio> #includ ...
- 用指针、子函数的方法去一维数组中所有元素的平均值,并放在a[0]处
<程序设计基础实训指导教程-c语言> ISBN 978-7-03-032846-5 p142 7.1.2 上级实训内容 [实训内容7]用指针.子函数的方法去一维数组中所有元素的平均值,并放 ...
- 函数指针与指针函数的区别
原文:http://yliangliang.blog.sohu.com/86320000.html 一.函数指针 首先它是一个指针,只是这个指针指向的是一个函数.指针变量可以指向变量的地址.数组.字符 ...
- 多态指针访问虚函数不能被继承的类快速排序N皇后问题插入排序堆排序merge归并排序栈上生成对象两个栈实现一个队列...
多态 /*1. 要想实现覆盖(重写)父类必须声明为virtual,子类可以不声明为virtual.-->FunB()2. 派生类重写基类的虚函数实现多态,要求函数名.参数列表.返回值完全相同.( ...
- 初论函数指针、指针函数、指针的指针
一.指针函数 1.定义 指针函数是指带指针的函数,即本质是一个函数.函数返回类型是某一类型的指针 函数返回值类型 函数名(参数表) int * f(int x,int y); //函数返回值类型是in ...
最新文章
- c语言两个数组按位合并,合并两个线性表(数组)并按照非递减排序输出,有点问题过来看看...
- docker官方文档中的dns,link,expose,publish
- Java使用正则表达式抓取日期和访问量
- PHP更新小程序,微信小程序Tab页切换更新数据详细介绍
- WPF中的动画——(三)时间线(TimeLine)
- 2016蓝桥杯C++A组第六题 寒假作业【暴力搜索】
- [GL]OpenGL 3D变换
- 斐波那契数列Java
- 微信小程序获取二维码报错:{“errcode“:47001,“errmsg“:“data format error hint:“}
- 天正的计算机快捷命令大全,天正建筑快捷键大全:天正建筑cad快捷键命令大全...
- 开源夏令营之项目汇报7
- 幼儿园手工之自制时钟_「时钟手工」幼儿园玩教具手工时钟,培养孩子的时间观念...
- qwin10如何删除linux系统,win 10内置了一个Linux子系统,以后使用Linux,不用那么麻烦了...
- border-radius的使用
- 统计工作随笔—同比与环比(同期为负值)、百分点
- 聊聊iOS中的网络加密
- Allegro/cadence中只有dra文件缺少psm解决方法
- LintCode领扣算法问题答案:374. 螺旋矩阵
- HP LaserJet 3050、3052、3055、3390和3392 AiO 系列产品 - 严重错误消息
- 基于XCP协议分析和理解