void (*f(int, void (*)(int)))(int) 函数解析 转
今天与几个同学看到了一个函数指针定义:
void (*f(int, void (*)(int)))(int)
以前在C trap pit fails里面见过,但是文章里面介绍的很详细,但是往往使初学者抓不到重点, 结果弄的一头污水。这里就简单介绍一下这中函数指针的定义方法。
什么是函数指针?
这个问题从定义的角度来看很好理解,指向函数的指针就是函数指针,但是我们如何声明一个函数指针呢?又如何将一个地址强制转换为某一个类型的函数指针呢?这里看下面一个例子源码:
void function(int a)
{
a = 5;
}
void (*pfunc)(int);
很简单,上面这段代码声明了一个函数fucntion和一个函数指针pfunc, 它指向的函数就是一个具有void返回值,int参数的函数。如果将function函数的地址给pfunc指针,可以简单的通过下面两种赋值:
pfunc = function;
或者
pfunc = &function;
通过指针调用该函数,也有两种方法:
pfunc(5); 或 (*pfunc)(5);
我们看一下赋值语句,pfunc = function; 但有时候可能是一个常数0x8999940, 它恰好也表示一个安全的与function相同的函数,如何将这个数值赋给pfunc呢?显然我们需要强制类型转换,应该将该常数转换成什么类型呢?这就是问题的关键!
在void (*pfunc)(int)语句里面,只有pfunc是变量名称,那么剩余的部分,void(*)(int),就是我们需要的转换类型。因此,新的赋值语句是:
pfunc = (void (*)(int)) 0x8999940;
赋值完成后,就可以通过pfunc(5); 或 (*pfunc)(5);调用相应的函数了。
如果理解了上面的内容,我们就可以解释void (*signal(int, void (*)(int)))(int)这个相对复杂的问题了
返回函数指针的函数声名
现在我们先抛开上面那个复杂的定义,先看一下下面的需求1) 定义一个函数;2) 该函数具有以下特点,两个参数,返回值是函数指针,并且一个参数也是函数指针。假如返回值和参数函数指针同为void (*)(int); 另一个函数参数是int型。该函数定义名称为my_func。
根据需求我们可以很容易定义出这种函数:
typedef void (*HANDLER)(int); // 参数函数和返回函数定义
HANDLER my_func(int, HANDLER);
突然需求中又不让使用typedef,这就是早期C语言不支持typedef的情况,那么如何定义这种函数呢?
我们假如说my_func的返回值是int,是不是它的定义可以这么写:
int my_func(int, void (*)(int));
也就是说,my_func(int, void (*)(int))就是一个int型数据。现在将int换成一个函数,也就是
void (*)(int) my_func)(int, void (*)(int);
这样一种定义,显然这种语法不支持,那么,实际是如何表示呢?回过头来,我们先看看函数指针的声明格式
void (*pfunc)(int);
其中pfunc 等价于 void (*)(int)。现在在看看上面的格式,是不是很相识,对了,pfunc就是my_func(int, void (*)(int))。现在如果将两者代替一下是不是就成了这种格式:
void (*my_func(int, void(*)(int)))(int)
如果将my_func换成signal,是不是就是我们文章开始提到的那个复杂声名?现在是不是明白了,原来如此啊,它是一个返回函数指针的的函数声名!
void (*f(int, void (*)(int)))(int) 函数解析 转的更多相关文章
- void (*f(int, void (*)(int)))(int) 函数解析
函数指针 今天与几个同学看到了一个函数指针定义: void (*f(int, void (*)(int)))(int) 以前在C trap pit fails里面见过,但是文章里面介绍的很详细,但是往 ...
- void f(int(&p)[3]){} 和void f(int(*p)[3]){}的差别
#include<iostream> using namespace std; void f(int(&p)[3]){ cout<<p[0]<& ...
- signal函数:void (*signal(int,void(*)(int)))(int);
http://blog.chinaunix.net/uid-20178794-id-1972862.html signal函数:void (*signal(int,void(*)(int)))(int ...
- (转+原)VC编译错误:uafxcw.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) 已经在 LIBCMT.lib(new.obj) 中定义
参考网址:http://zhanyonhu.blog.163.com/blog/static/16186044201023094754832/ 1>uafxcw.lib(afxmem.obj) ...
- “void * __cdecl operator new(unsigned int)”(??2@YAPAXI@Z) already defined in LIBCMTD.lib(new.obj)
转自VC错误:http://www.vcerror.com/?p=1377 问题描述: 当 C 运行时 (CRT) 库和 Microsoft 基础类 (MFC) 库的链接顺序有误时,可能会出现以下 L ...
- Solve Error: nafxcw.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new[](unsigned int)" (??_U@YAPAXI@Z) already defined in libcpmt.lib(newaop.obj)
Error: nafxcw.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new[](unsigned int)&quo ...
- uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)"解决办法
如果在编译MFC程序的时候出现下列及类似的错误: 1>uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator ...
- MFC程序出现uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)解决办法
在同一个地方摔倒两次之后,决定记录下来这个东西. 问题 1>uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl opera ...
- STL函数static void (* set_malloc_handler(void (*f)()))()与函数指针解析
在C++ STL的SGI实现版本中,一级空间配置器class __malloc_alloc_template中有一个静态函数的实现如下: static void (*set_malloc_handle ...
随机推荐
- Pgsql数据库jsonb操作函数集合
CREATE OR REPLACE FUNCTION "json_object_del_path"( "json" json, "key_path&q ...
- Day 3 @ RSA Conference Asia Pacific & Japan 2016 (afternoon)
13.30 hrs Keynote Security in the World-Sized Web Bruce Schneier,Chief Technology Officer, Resili ...
- jdk的动态代理
至于jdk的动态代理怎么用此处并不多说,现在是更深一步的理解,jdk的Proxy类到底做了什么. Proxy.newProxyInstance可以生成代理类,此方法有三个参数(ClassLoader ...
- EPPlus与Excel完美的结合
本文转载:http://www.cnblogs.com/olartan/archive/2012/07/14/2591711.html 笔者近期在公司项目中需要生产比较复杂的Excel报表, 问题点是 ...
- 编译C++,找不到头文件(fatal error: string: No such file or directory)
在androidproject中编译C++时,找不到头文件,报错例如以下: fatal error: string: No such file or directory 解决该问题须要在Android ...
- mysql查询随机几条数据(速度快)
MySql查询随机几条数据 想到了 Max RAND 这几个函数 用以下2种办法都可以实现查询. 速度还行. 几十万数据左右, 没有什么问题. SELECT * FROM `news` WHERE i ...
- linux route命令学习
route命令用于显示和操作IP路由表. 没有增加路由之前,route命令的结果如下, sh-# route Kernel IP routing table Destination Gatew ...
- ios6如何处理内存,分别为前警告后
这里有一篇文章.非常具体地说明了ios6前后是怎样处理内存警告的: 来自唐巧的技术博客:http://blog.devtang.com/blog/2013/05/18/goodbye-viewdidu ...
- Swift 实现图片转字符画的功能
本文介绍一个IOS APP , 将图片转换成ASCII字符画,使用Swift语言编写. 举个例子,我们使用著名的蕾娜照片作为原图片 经APP转换后形成的字符画,我们打印出来,效果如下: 放大她的脸部可 ...
- Java jdbc数据库连接池总结!(转)
1. 引言 近年来,随着Internet/Intranet建网技术的飞速发展和在世界范围内的迅速普及,计算机 应用程序已从传统的桌面应用转到Web应用.基于B/S(Browser/Server)架构的 ...