kenlistian

厚积薄发. 勤为桨,思为帆

   :: 首页 :: 新随笔 ::  :: 聚合  :: 管理 ::
  73 随笔 :: 4 文章 :: 22 评论 :: 0 Trackbacks

一个函数指针的理解:
 有一段程序存储在起始地址为 0的一段内存上,如果我们想要调用这段程序,请问该如何去做?
 答案是 (*(void (*)( ) )0)( )。

 首先,最基本的函数声明: void function (paramList);
 最基本的函数调用: function(paramList);

  鉴于问题中的函数没有参数,函数调用可简化为 function();
   根据问题描述,可以知道 0是这个函数的入口地址,也就是说,0是一个函数的指针。
   使用函数指针的函数声明形式是:void (*pFunction)(),相应的调用形式是: (*pFunction)(),
   则问题中的函数调用可以写作:(*0)( )。

  大家知道,函数指针变量不能是一个常数,因此上式中的 0必须要被转化为函数指针。

  我们先来研究一下,对于使用函数指针的函数:
        比如 void (*pFunction)( ),函数指针变量的原型是什么?
    这个问题很简单,pFunction函数指针原型是( void (*)( ) ),即去掉变量名,
    清晰起见,整个加上()号。

  所以将 0强制转换为一个返回值为void,参数为空的函数指针如下:( void (*)( ) )。

   OK,结合2)和3)的分析,结果出来了,那就是:(*(void (*)( ) )0)( ) 。

  答案分析:从头到尾理解答案

   (void (*)( )) ,是一个返回值为void,参数为空的函数指针原型。
   (void (*)( ))0,把0转变成一个返回值为void,参数为空的函数指针,指针指向的地址为0.
   *(void (*)( ))0,前面加上*表示整个是一个返回值为void的函数的名字
   (*(void (*)( ))0)( ),这当然就是一个函数了。

  我们可以使用 typedef清晰声明如下:

   typedef void (*pFun)();

这样定义之后,pFun就是一个返回类型为void无参数的函数指针变量了。

  这样函数变为 (*(pFun)0)();


----
在调用动态库时,习惯用typedef重新定义动态库函数中的函数地址(函数指针),
如在动态库(test.dll)中有如下函数:
int DoCase(int, long);

则,在调用动态库是有两种方法:
1. 先声明一个与动态库中类型一致的指针函数变量:
int (*DOCASE)(int ,long);  //用于指向动态库中的DoCase函数地址
HINSTANCE gLibMyDLL = NULL;
gLibMyDLL 
= LoadLibrary("test.dll");
if(gLibMyDLL != NULL)
{
  DOCASE 
= (int(*)(int,long))GetProcAddress(gLibMyDLL, "DoCase");
}
int s = DOCASE(1,1000);

2.用typedef定义一个指针函数:
typedef (
*DOCASE)(int ,long);

HINSTANCE gLibMyDLL 
= NULL;
DOCASE _docase;
gLibMyDLL 
= LoadLibrary("test.dll");
if(gLibMyDLL != NULL)
{
  _docase 
= (DOCASE)GetProcAddress(gLibMyDll, "DoCase");
}

int s=_docase(1,1000);


----------------
在C++类中使用函数指针。
//typedef 返回类型(类名::*新类型)(参数表)
class CA
{
public:
  
char lcFun(int a){ return; }
};

CA ca;
typedef 
char (CA::*PTRFUN)(int);
PTRFUN pFun;
void main()
{
  pFun 
= CA::lcFun;
  ca.(
*pFun)(2);
}


指针的定义与使用都加上了“类限制”或“对象”,用来指明指针指向的函数是哪个类的,
这里的类对象也可以是使用new得到的。
如:
CA *pca = new CA;
pca->(*pFun)(2);
delete pca;
而且这个类对象指针可以是类内部成员变量,你甚至可以使用this指针。
如:类CA有成员变量PTRFUN m_pfun;
void CA::lcFun2()
{
   (this->*m_pFun)(2);
}
一句话,使用类成员函数指针必须有“->*”或“.*”的调用。


--------------------

void test(void* );
void tt()
{
   printf(
"kao,没玩过这种\n");
}

int main(int argc, char* argv[])
{
    typedef 
void(*Fun)();
    Fun mytest;
    mytest 
= tt;
    test((
void*)mytest);
    
return 0;
}

void test(void * p)
{
    (
*(void(*)())p)();
}


posted on 2008-10-29 22:23 kenlistian 阅读(787) 评论(1)  编辑 收藏 引用 所属分类: cpp

评论

# re: 汇总函数指针理解[未登录] 2008-10-31 17:15 908971
受教了  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理