指向函数的指针 分类: C/C++ 2015-07-13 11:03 14人阅读 评论(0) 收藏
原文网址:http://www.cnblogs.com/zxl2431/archive/2011/03/25/1995285.html
讲的很清楚,备份记录。
(一) 用函数指针变量调用函数
可以用指针变量指向整形变量、字符串、数组、结构体、也可以指向一个函数。一个函数在编译时被分配一个入口地址。这个入口地址就称为函数指针。可以用一个指针变量指向函数,然后通过该指针变量调用此函数。用简单的数值比较为例:
#include <stdio.h>
int main()
{
int max(int,int);
int (*p)(int,int);
int a,b,c;
p = max;
scanf("%d,%d",&a,&b);
c = (*p)(a,b);
printf("a=%d,b=%d,max=%d\n",a,b,c);
return 0;
}
int max(int x,int y)
{
int z;
if(x>y) z = x;
else z = y;
return(z);
}
main函数中的” c = max(a,b); ” 包括了一次函数的调用。每一个函数都占用一段内存单元。因此,可以用一个指针变量指向一个函数,通过指针变量来访问它指向的函数。
第7行:int (* p)( int,int ); 用来定义 p 是一个指向函数的指针变量,该函数有两个整形参数,函数值为整形。注意 * p 两侧的括号不可省略,表示 p 先与 * 结合,是指针变量,然后再与后面的 ( ) 结合,表示此指针变量指向函数,这个函数值 (即函数的返回值) 是整形的。如果写成 int * p ( int,int ) ,由于( )的优先级高于 *,它就成了声明一个函数P( 这个函数的返回值是指向整形变量的指针)。
赋值语句 p = max ; 作用是将函数 max 的入口地址赋给指针变量p。和数组名代表数组首元素地址类似,函数名代表该函数的入口地址。这时 p 就是指向函数 max 的指针变量,此时 p 和 max都指向函数开头,调用 * p 就是调用 max 函数。但是p作为指向函数的指针变量,它只能指向函数入口处而不可能指向函数中间的某一处指令处,因此不能用 *(p + 1)来表示指向下一条指令。
注意:
(1) 指向函数的指针变量的一般定义形式为:
数据类型 (*指针变量名)(函数参数列表)
这里数据类型就是函数返回值的类型
(2) int (* p) ( int,int ); 它只是定义一个指向函数的指针变量 p, 它不是固定指向哪一个函数的,而只是表示定义这样一个类型的变量,它是专门用来存放函数的入口地址的。在程序中把哪一函数(该函数的值应该是整形的,且有两个整形参数)的地址赋给它,他就指向哪一个函数。在一个函数中,一个函数指针变量可以先后指向同类型的不同函数。
(3) p = max; 在给函数指针变量赋值时,只需给出函数名而不必给出函数参数,因为是将函数的入口地址赋给 p ,而不涉及 实参和形参的结合问题,不能写成 p = max(a,b);
(4) c = (*p)(a,b) 在函数调用时,只需将( *p ) 代替函数名即可,后面实参依旧。
(5) 对于指向函数的指针变量,像 p++ ,p+n…..是无意义的。
(二) 用指向函数的指针作为函数参数
函数指针变量通常的用途之一就是把指针作为参数传递到其他函数。
函数的参数可以是变量、指向变量的指针变量、数组名、指向数组的指针变量,也可以是指向函数的指针也可以作为参数,以实现函数地址的传递,这样就能够在被调用的函数中使用实参函数。
void sub ( int ( *x1) (int), int (*x2) (int,int) )
{
int a,b,i,j;
a = (*x1)(i); /* 调用 f1 函数 */
b = (*x2)(i)(j); /* 调用 f2 函数 */
}
如果实参为两个 函数名 f1 和 f2. 在函数首部定义x1、x2为函数指针变量,x1指向的函数有一个整形形参,x2指向的函数有两个形参。i 和 j 是函数f1 和 f2所要的参数。函数sub的形参 x1、x2(指针变量)在函数 sub 未被调用时并不占用内存单元,也不指向任何函数。在sub被调用时,把实参函数 f1 和 f2的入口地址传给形式指针变量 x1 和 x2.
既然在 sub 函数中要调用 f1 和 f2 函数,为什么不直接调用f1 和 f2而要用函数指针变量呢? 确实,如果只是用到f1 和 f2 函数,完全可以在sub函数中直接调用f1 和 f2,而不必设指针变量 x1 和 x2。 但是,如果在每次调用sub时,调用的函数不是固定的,下次是f3 和 f4,再是f5 和 f6…这时用指针变量就比较方便了。
指向函数的指针 分类: C/C++ 2015-07-13 11:03 14人阅读 评论(0) 收藏的更多相关文章
- javascript的全局变量 分类: C1_HTML/JS/JQUERY 2014-08-07 11:03 562人阅读 评论(0) 收藏
javascipt是一门面向对象的编程语言.由于存在一些全局属性及全局函数,因此可以认为存在一个全局变量,这些全局属性及全局函数均是其属性或函数. 在js核心中,并没有定义一个具体的全局变量,因此,j ...
- MS SQLServer 批量附加数据库 分类: SQL Server 数据库 2015-07-13 11:12 30人阅读 评论(0) 收藏
************************************************************ * 标题:MS SQLServer 批量附加数据库 * 说明:请根据下面的注释 ...
- Javascript图片预加载详解 分类: JavaScript HTML+CSS 2015-05-29 11:01 768人阅读 评论(0) 收藏
预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...
- UI基础:UI程序执行顺序(UIApplicationMain()函数),自定义视图 分类: iOS学习-UI 2015-07-02 22:09 68人阅读 评论(0) 收藏
UI程序的一般执行顺序: 先进入main里面,执行函数UIApplicationMain(),通过该函数创建应用程序对象和指定其代理并实现监听,当执行函数UIApplicationMain()时还会做 ...
- 分类算法简介 分类: B10_计算机基础 2015-03-09 11:08 257人阅读 评论(0) 收藏
一.决策树 决策树是用于分类和预测的主要技术之一,决策树学习是以实例为基础的归纳学习算法,它着眼于从一组无次序.无规则的实例中 推理出以决策树表示的分类规则.构造决策树的目的是找出属性和类别间的关系, ...
- Makefile 入门与基本语法 分类: C/C++ ubuntu 2015-05-18 11:16 466人阅读 评论(0) 收藏
在我看来,学会写简单的Makefile,阅读较复杂的makefile,是每一个Linux程序员都必须拥有的基本素质.Makefile可以自动识别哪些源文件被更改过,需要重新编译,那些不需要.从而节省大 ...
- C# ArrayList 基本用法 分类: C# 2014-09-26 11:03 524人阅读 评论(0) 收藏
首先说明一下ArrayList 与 数组的区别: (1)ArrayList 的容量可以根据需要自由扩充,数组的容量是固定的 (2)ArrayList 只能是一维形式,数组可以是多维的 (3)Array ...
- Windows平台下解决Oracle12c使用PDB数据库创建SDE的问题 分类: oracle sde 2015-06-12 11:03 88人阅读 评论(0) 收藏
Windows平台下解决Oracle12c使用PDB数据库创建SDE的问题 Oracle 12C中引入了CDB与PDB的新特性,在ORACLE 12C数据库引入的多租用户环境(Multitenant ...
- 动态规划:最大连续子序列乘积 分类: c/c++ 算法 2014-09-30 17:03 656人阅读 评论(0) 收藏
题目描述: 给定一个浮点数序列(可能有正数.0和负数),求出一个最大的连续子序列乘积. 分析:若暴力求解,需要O(n^3)时间,太低效,故使用动态规划. 设data[i]:第i个数据,dp[i]:以第 ...
随机推荐
- IT从业人员必看的十几个论坛
IT方面的论坛太多了,有综合,有专业,有行业,在各个论坛里混了几年,体会颇深,以前是论坛哪里人多,往哪里去,新浪论坛,网易是经常去的,人多啊,好几十万,去了以后才发现没有意思,没有共同的语言,于是逛专 ...
- contos vsftp 530错误
只需要把/etc/pam.d/vsftpd文件中的 auth required pam_listfile.so item=user sense=deny file=/etc/vsft ...
- AFNetworking的原理与基本使用-b
全称是AFNetworking 虽然运行效率没有ASI高,但是使用比ASI简单 是对NSURLConnection和NSURLSession的各自的一层包装 AFN的内部中的RunLoop AFN内部 ...
- python的方法总结:
1. Python的字典的items(), keys(), values()都返回一个list >>> dict = { 1 : 2, 'a' : 'b', 'hello' : 'w ...
- 【技术贴】解决Program Files文件夹消失
好久不写程序了,今天良心发现,就寻找一下自己是否安装了JDK,习惯性的去C盘的Program Files的文件夹下面去找,次奥,没有这个文件夹.好吧.是在玩我么. 于是 打开cmd 输入如下命令 AT ...
- xapian安装
xapian安装:$ su enter your root password # rpm -ivh http://rpm.eprints.org/rpm-eprints-org-key-1-1.noa ...
- X86汇编快速入门
http://www.cnblogs.com/YukiJohnson/archive/2012/10/27/2741836.html
- jQueryEasyUI中DataGrid的height,width,fit,fitColumns属性
height: 600, //不指定则默认垂直包裹,指定了则固定 width:1200,//不指定则水平100%平铺,指定了则固定 fit:false,//true:高度填充父窗体,忽略height属 ...
- 使用vs自带的wcf配置工具
服务和行为是并列的 对应到配置文件中 wcf的配置在system.serviceModel中 可以有多个服务 一个服务会有一个主机以及多个终结点 主机包含多个基址 baseAddress 终结点,由 ...
- Linux route命令详解和使用示例(查看和操作IP路由表)
Linux系统的route命令用于显示和操作IP路由表(show / manipulate the IP routing table).要实现两个不同的子网之间的通信,需要一台连接两个网络的路由器,或 ...