函数指针与指针函数以及typedef

  c难于理解的是指针,其魅力之处也是指针,函数方法结构,化繁为简可以理解为:返回值 函数名(形参表),具体来说:

返回值:1.可以为空void

    2.基本数据类型char short int long float double

    3.指针

形参表跟返回值一样,这里面最复杂最难理解的是指针,因为指针本身是一个变量,里面保存的是地址,而地址的类型是由指针定义的时候申明的,而指针又可以指向函数,这样一搭配就非常复杂了。我们从一个复杂的程序开始:

          void(*signal(int sig_num,void(*handler)(int)))(int)

第一看到都会头晕,不过抽丝剥茧之后发现也就那么回事。从最外层分析: void(*fb)(int),这是一个函数指针,fb=signal(int sig_num,void(*handler(int)))。这是一个函数,只不过这个函数一个参数是int,一个参数是函数指针。

两个这么一结合,发现fb是函数,这个函数返回值是一个函数指针,而这个函数指针指向的函数返回值是void 参数是int。只不过这些写难以理解,但是利用typedef将这个函数指针“封装”起来就很好理解了。

  typedef void(*func_p)(int);

上面是将func_p声明为 void ()(int)这样函数结构的函数指针。创造了一种新的指针类型,那么signal函数就可以简化成:

  func_p signal(int sig_num,func_p p);

这么一写,就跟我们平常使用的函数结构一样了,好理解多了。

注意定义函数指针的写法: void (*funcP)(void)。指向void ()(int)函数的,这与基本数据类型指针不同:int* ip;

至于函数返回值又是函数指针的情况,那样的写法了解一下就行,一般用typedef简化。至于调用函数指针指向函数的方式就调用函数的写法一样。

//自定义func_p为新的指针类型
typedef void (*func_p)(int);

void callback(int x)
{
    printf("callback:%d\r\n",x);
}
//普通函数返回值是指针
int* function(int* p)
{
    int* q;
    q = (int*)malloc(sizeof(int)*10);
    *q = *p;
    return q;
}
//函数返回值是函数指针,函数体的参数是普通指针
void (*function1(int* p))(int)
{
    printf("p:%d\r\n",*p);
    return callback;
}
//函数返回值是函数指针,而函数形参也有函数指针,注意函数指针作为函数形参的写法
void (*function3(int*p,void(*handler)(int)))(int)
{
    void (*func_temp)(int);//函数指针的写法,与形参handler写法是一样的。
    func_temp = handler;
    printf("p:%d\r\n",*p);
    return handler;//函数的返回值是函数指针,这里形参的函数指针类型与返回值函数指针的类型是一样的都是void ()(int)
}
//利用typedef定义的新指针类型重写的函数,更好理解。
func_p function2(int* p)
{
    printf("p:%d\r\n",*p);
    return callback;
}

验证:

int main(int argc, char *argv[]) {
    int a = 100;
    int* iq;
    void (*funcp)(int);
    void (*funcp2)(int) = callback2;//定义函数指针并赋值,直接赋函数名
    funcp2(1001);
    iq = function(&a);//函数值是指针,注意这里返回的指针是函数中在堆空间申请的空间,如果不free是不会被收回的。
                      //而函数体中定义的零时指针是函数栈空间。当函数体结束会被收回。因此返回的是无效地址。

    funcp = function3(&a,callback2);//调用函数返回值跟参数都是函数指针的函数。function3有一个普通指针参数。
                                    //将函数callback2传入,这个函数会被返回给funcp。这个时候函数指针指向的函数体是callback2
    funcp(1000); //执行指向的函数体
    printf("ret:%d\r\n",*iq);
    system("pause");
    return 0;
}

执行结果:

posted @ 2016-10-29 11:23  麦哈顿博士  阅读(1388)  评论(0编辑  收藏  举报