函数指针

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

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. QQ原创表情添加

    有时候与QQ好友聊天时会收到一些自己比较喜欢的原创表情,如果我们想把这些QQ不支持直接保存的原创表情保存到电脑上该怎么做呢?我们以原创表情图片为例简单介绍一下. 首先,先建立一个存放表情图片的文件夹. ...

  2. Ajax 技术原理(转)

    Ajax 技术原理 2010-01-04 原文出处:http://www.nowamagic.net/ajax/ajax_AjaxPrinciple.php 在写这篇文章之前,曾经写过一篇关于AJAX ...

  3. C程序设计语言练习题1-20

    练习1-20 编写程序detab,将输入中的制表符替换成适当数目的空格,使空格充满到下一个制表符终止位的地方.假设制表符终止位的位置是固定的,比如每隔n列就会出现一个制表符终止位.n应该是变量还是符号 ...

  4. GDI相关函数

    GetWindowRect计算窗口大小 MoveWindow 设置窗口大小 SetMapMode 该函数设置指定设备环境的映射方式 MM_LOMETRIC:每个逻辑单位转换为0.1毫米,X正方向向右, ...

  5. Unity3D 经验记录

    1.using UnityEngine.SceneManagement; 当在01场景调用02场景时,再载入回01场景时,代码保存的变量不会初始化,预制物体脚本内的变量会初始化. 2.当子物体太多时, ...

  6. 【原创】CLEVO P157SM外接鼠标键盘失灵解决:更换硅脂(附带最新跑分数据)

    作者批注:本文允许转载,并且希望给搜索未来人类.蓝天.CLEVO.更换硅脂或者任何有关关键字的朋友提供帮助. 原文地址:http://www.cnblogs.com/c4isr/p/3514140.h ...

  7. Entity Framework with MySQL 学习笔记一(关系整理版)

    1-1 设置 //DataAnnotation 1-1 | 1-0 table //SQLtable : member , columns : memberId, name //SQL basic l ...

  8. json与jsonp ajax

    今天在网上找了一下资料,发现这篇文章总结得好,果断转了:http://blog.csdn.net/superhosts/article/details/9057301

  9. 【转】VS2013中如何解决error C4996: 'fopen'问题

    原文网址:http://jingyan.baidu.com/article/ce436649fd61543773afd32e.html 今天编写控制台应用程序时出现如下错误 error C4996: ...

  10. android 再按一次退出程序(实现代码)

    效果如图: 实现代码: private long exitTime = 0; /** * 捕捉返回事件按钮 * * 因为此 Activity 继承 TabActivity 用 onKeyDown 无响 ...