zoukankan      html  css  js  c++  java
  • 函数指针与指针函数以及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
    ",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
    ",*p);
        return callback;
    }
    //函数返回值是函数指针,而函数形参也有函数指针,注意函数指针作为函数形参的写法
    void (*function3(int*p,void(*handler)(int)))(int)
    {
        void (*func_temp)(int);//函数指针的写法,与形参handler写法是一样的。
        func_temp = handler;
        printf("p:%d
    ",*p);
        return handler;//函数的返回值是函数指针,这里形参的函数指针类型与返回值函数指针的类型是一样的都是void ()(int)
    }
    //利用typedef定义的新指针类型重写的函数,更好理解。
    func_p function2(int* p)
    {
        printf("p:%d
    ",*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
    ",*iq);
        system("pause");
        return 0;
    }

    执行结果:

    这个只不过是自己的流水账,偶尔有一些心得,错误的地方概不负责
  • 相关阅读:
    四招打造复合型人才
    Eclipse多国语言包的安装
    怎样和人配合(转)
    看海外如何解困建筑信息化(转)
    SSRS重装后不能在SSMS和IIS中打开,报Unauthorized错误的解决办法
    小心调用Replicator, While 和 CAG子活动
    自动备份 SourceSafe
    SQLServer2005新增序列功能的几个函数:ROW_NUMBER, RANK, DENSE_RANK, and NTILE
    分析物语
    定位.Net程序集文件
  • 原文地址:https://www.cnblogs.com/ashitaka/p/6010510.html
Copyright © 2011-2022 走看看