zoukankan      html  css  js  c++  java
  • 《C与指针》——高级指针话题

    指针真是让人又爱又恨。。。。。

    首先还是先来看一下C语言中的高级指针声明。不要被表面迷惑最重要。

    /*
    ** 《C和指针》——高级指针话题 
    */
    
    
    int i;        //定义一个整型变量  
    int *pi;    //指向整型变量的指针  
    int **ppi;    //指向一个指针,而那个指针又指向一个整型变量  
    
    
    /*高级声明*/
    
    int fun();         //普通函数声明,返回一个整数 
     
    int *fun();        //首先他是一个函数,但是他想返回一个指向整型的指针 
    
    int (*fun)();     //这就是一个指针了,他指向一个返回整型的函数,这个fun叫做“函数指针”,指向函数的指针  
    
    int *(*fun)();    //这个和上面那个差不多嘛,函数指针喽,只是这个函数返回一个指向整型的指针。 
    
    int f[];          //这是一个整型数组啊 
    
    int *f[];         //这也是一个数组,因为下标的优先级高,只不过这个数组里面都是指向整型的指针啊 
    
    int f()[];        //非法操作 
    
    int f[]();        //非法操作 
    
    int (*f[])();    //首先他是一个数组,数组里面全是指针,这些指针指向返回值为整型的函数。 
    
    int *(*f[])();    //和上面一样,只不过这个函数返回整型指针。

    函数指针:主要用途是实现“回调函数”和“转移表”

    (1)、回调函数:把一个函数指针作为参数传递给其他的函数。

    在《C与指针》中,作者指出:任何时候,如果你所编写的函数必须能够在不同的时刻执行不同类型的工作,或者执行只能由函数调用者定义的工作,都可以使用回调函数。许多窗口系统使用回调函数连接过个动作,如拖拽鼠标和点击按钮来指定程序中的某个特定的函数。

    比如我们我们平时写的查找函数,每一个查找函数只能查找某一类型的数据,int型、char型,但是有没有一种函数能查找所有类型的数据呢?这时就需要函数指针来编写一个回调函数了。

    首先调用者需要编写一个函数,用来比较两个值,然后把一个指向这个函数的指针作为参数传递给查找函数,然后查找函数调用你编写的那个函数来进行查找。

    其实这个样子就像是,查找函数像是一个分拣机,你编写的比较函数可以比喻成分拣机上的传感器,给他一个能识别黑色的传感器,那么分拣机就会只把黑色的东西分拣出来,给他一个识别红色的传感器,就把红色的东西给分拣出来。

    下面这个例子是《C和指针》里面,作者给出的链表中查找的例子:

    /*
    ** 在一个单链表中查找一个指定值 
    */
    node *search_list(node *node_,void const *value,int (*compare)(void const *,void const *))
    {
        while(node_ != NULL)
        {
            if(compare(&node_->value,value) == 0)
                break;
            node_ = node_->link;
        }
        return node_;
    }
    
    /*
    ** 用户可以自定义自己的比较函数 
    ** 比较整型就强制转换为整型 
    */ 
    int compare(void const *a,void const *b)
    {
        if(*(int *)a == *(int *)b)
            return 0;
        else
            return 1;
    }

    调用方式:

    /*
    ** 回调函数的调用方式
    ** 因为函数名本身就是地址,所以并不需要取地址,不过也可以。 
    */
    discard_node = search_list(root,&desired_value,compare_ints) ;

    这位博主也说了一下回调函数的一个作用——开发者可以将自己实现的函数细节进行封装,然后将头文件提供给用户。

    https://blog.csdn.net/morixinguan/article/details/65494239

    (2)、转移表:就是函数指针数组,他把具体操作和和选择操作的代码分离,是程序结构更加突出。

    比如我们有时可能需要在switch语句中调用函数,当情况很多的时候,这个switch语句将会很长,如果表示操作符的代码是从0开始的连续整数,这时我们就可以使用转移表来代替switch语句来实现不同情况的函数选择。

    还是直接来看例子:

    /*
    ** 利用转移表实现多个函数的选择 
    */
    double add(double,double); 
    double sub(double,double); 
    double mul(double,double); 
    double div(double,double);
    //.........
    
    double (*oper_fun[])(double,double) = {
        add,sub,mul,div......
    }

    转移表的调用方式:

    result = oper_fun[fun_num](num1,num2);

    特别注意:使用转移表要特别注意下标的越界检查,保证下标位于合法的范围。

    当然,上面提到的回调函数与转移表都只是很简单的应用,目的在于理解最基本的操作与原理。

  • 相关阅读:
    解题:POI 2009 TAB
    解题:POI 2015 Pieczęć
    解题:POI 2013 Taxis
    解题:POI 2015 Kinoman
    题目1012:畅通工程(并查集)
    并查集深入分析
    题目1186:打印日期(日期计算)
    C/C++如何整行读入字符串?
    四种方法解决最大连续子序列和问题
    题目1011:最大连续子序列
  • 原文地址:https://www.cnblogs.com/qsyll0916/p/8671617.html
Copyright © 2011-2022 走看看