今天与几个同学看到了一个函数指针定义:

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) 函数解析 转的更多相关文章

  1. void (*f(int, void (*)(int)))(int) 函数解析

    函数指针 今天与几个同学看到了一个函数指针定义: void (*f(int, void (*)(int)))(int) 以前在C trap pit fails里面见过,但是文章里面介绍的很详细,但是往 ...

  2. void f(int(&p)[3]){} 和void f(int(*p)[3]){}的差别

    #include<iostream> using namespace std; void f(int(&p)[3]){          cout<<p[0]<& ...

  3. signal函数:void (*signal(int,void(*)(int)))(int);

    http://blog.chinaunix.net/uid-20178794-id-1972862.html signal函数:void (*signal(int,void(*)(int)))(int ...

  4. (转+原)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) ...

  5. “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 ...

  6. 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 ...

  7. uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)"解决办法

    如果在编译MFC程序的时候出现下列及类似的错误: 1>uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator ...

  8. MFC程序出现uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)解决办法

    在同一个地方摔倒两次之后,决定记录下来这个东西. 问题 1>uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl opera ...

  9. STL函数static void (* set_malloc_handler(void (*f)()))()与函数指针解析

    在C++ STL的SGI实现版本中,一级空间配置器class __malloc_alloc_template中有一个静态函数的实现如下: static void (*set_malloc_handle ...

随机推荐

  1. Pgsql数据库jsonb操作函数集合

    CREATE OR REPLACE FUNCTION "json_object_del_path"( "json" json, "key_path&q ...

  2. 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 ...

  3. jdk的动态代理

    至于jdk的动态代理怎么用此处并不多说,现在是更深一步的理解,jdk的Proxy类到底做了什么. Proxy.newProxyInstance可以生成代理类,此方法有三个参数(ClassLoader ...

  4. EPPlus与Excel完美的结合

    本文转载:http://www.cnblogs.com/olartan/archive/2012/07/14/2591711.html 笔者近期在公司项目中需要生产比较复杂的Excel报表, 问题点是 ...

  5. 编译C++,找不到头文件(fatal error: string: No such file or directory)

    在androidproject中编译C++时,找不到头文件,报错例如以下: fatal error: string: No such file or directory 解决该问题须要在Android ...

  6. mysql查询随机几条数据(速度快)

    MySql查询随机几条数据 想到了 Max RAND 这几个函数 用以下2种办法都可以实现查询. 速度还行. 几十万数据左右, 没有什么问题. SELECT * FROM `news` WHERE i ...

  7. linux route命令学习

    route命令用于显示和操作IP路由表. 没有增加路由之前,route命令的结果如下, sh-# route Kernel IP routing table Destination     Gatew ...

  8. ios6如何处理内存,分别为前警告后

    这里有一篇文章.非常具体地说明了ios6前后是怎样处理内存警告的: 来自唐巧的技术博客:http://blog.devtang.com/blog/2013/05/18/goodbye-viewdidu ...

  9. Swift 实现图片转字符画的功能

    本文介绍一个IOS APP , 将图片转换成ASCII字符画,使用Swift语言编写. 举个例子,我们使用著名的蕾娜照片作为原图片 经APP转换后形成的字符画,我们打印出来,效果如下: 放大她的脸部可 ...

  10. Java jdbc数据库连接池总结!(转)

    1. 引言 近年来,随着Internet/Intranet建网技术的飞速发展和在世界范围内的迅速普及,计算机 应用程序已从传统的桌面应用转到Web应用.基于B/S(Browser/Server)架构的 ...