zoukankan      html  css  js  c++  java
  • 函数指针

    @

    函数指针

    定义

    函数指针(也称为子例程指针或过程指针)是指向函数的指针。与引用数据不同, 函数指针指向内存中的可执行代码。解引用函数指针时, 就如同引用函数一样, 可以调用和传递参数。 这样的调用就称之为间接调用, 因为函数是通过变量间接调用的,而不是直接通过固定的标识符或地址调用。

    声明

    类型说明符 (*函数名) (参数)
    

    比如

    int (*p)(int x, int  y);// 该函数指针对应的函数指针类型为 int (*) (int a, int b);
    void (*foo)(int);
    

    初始化

    • 方式一:对应的函数名赋值给变量
    • 方式二:函数名前加 & 符号再赋值给变量

    其实两种方式是一样的。 就如同数组, 我们可以通过 &变量名 的方式取得数组的地址, 也可以通过直接 变量名 取得地址。

    举例

    double cm_to_inches(double cm) 
    {
    	return cm / 2.54;
    }
    double (*func1)(double) = cm_to_inches;
    // 或 double (*func1)(double) = &cm_to_inches;
    

    c 语言中的示例

    #include <stdio.h>  /* for printf */
    #include <string.h> /* for strchr */
    
    double cm_to_inches(double cm) 
    {
    	return cm / 2.54;
    }
    
    // "strchr" is part of the C string handling (i.e., no need for declaration)
    // See https://en.wikipedia.org/wiki/C_string_handling#Functions
    
    int main(void) 
    {
    	double (*func1)(double) = cm_to_inches;
    	char * (*func2)(const char *, int) = strchr;
    	printf("%f %s", func1(15.0), func2("Wikipedia", 'p'));
    	/* prints "5.905512 pedia" */
    	return 0;
    }
    

    结果
    运行结果与原函数一致
    直接调用函数, 肯定是比使用函数指针方便, 容易。而函数指针在作为回调函数时可以让我们的编程变得更加简单。

    #include <math.h>
    #include <stdio.h>
    
    
    // Function taking a function pointer as an argument
    double compute_sum(double (*funcp)(double), double lo, double hi)
    {
        double sum = 0.0;
        // Add values returned by the pointed-to function '*funcp'
        int i;
        for(i = 0;  i <= 100;  i++) 
        {
            // Use the function pointer 'funcp' to invoke the function
            double x = i / 100.0 * (hi - lo) + lo;
            double y = funcp(x);
            sum += y;
        }
        return sum / 101.0;
    }
    
    double square(double x) 
    {
         return x * x;
    }
    
    int main(void) 
    {
        double  sum;
        // Use standard library function 'sin()' as the pointed-to function
    
        sum = compute_sum(sin, 0.0, 1.0);
        printf("sum(sin): %g
    ", sum);
        
        // Use standard library function 'cos()' as the pointed-to function
        sum = compute_sum(cos, 0.0, 1.0);
        printf("sum(cos): %g
    ", sum);
    
        // Use user-defined function 'square()' as the pointed-to function
    
        sum = compute_sum(square, 0.0, 1.0);
        printf("sum(square): %g
    ", sum);
    
        return 0;
    
    }
    

    结果
    运行结果
    在以上的函数中, 使用函数指针在另一个函数(compute_sum)中调用所传入的函数(如 sin, con, square)。在该过程中, compute_sum函数通过funcp所传入的函数, 实现compute_sum函数达到不同的效果。

    与typedef结合

    在实际的使用过程中, 为了更易于阅读, 更多的会结合typedef方式进行。

    #include <stdio.h>  /* for printf */
    #include <string.h> /* for strchr */
    
    typedef double(*Func1)(double);
    typedef char* (*Func2)(const char *, int);
    
    double cm_to_inches(double cm) 
    {
    	return cm / 2.54;
    }
    
    int main(void) 
    {
    	Func1 func1 = cm_to_inches;
    	Func2 func2 = strchr;
    	printf("%f %s", func1(15.0), func2("Wikipedia", 'p'));
    	/* prints "5.905512 pedia" */
    	return 0;
    }
    

    函数指针数组

    其声明如下

    类型说明符 (*函数名[数组长度]) (参数) 
    

    举个例子

    #include <stdio.h>  /* for printf */
    
    char * fun1(char * p)
    {
    	printf("%s
    ", p);
    	return p;
    }
    char * fun2(char * p)
    {
    	printf("%s
    ", (p+1));
    	return p;
    }
    char * fun3(char * p)
    {
    	printf("%s
    ", (p+2));
    	return p;
    }
    int main() {
    	char * (*pf[3])(char * p);
    	pf[0] = fun1; 
    	pf[1] = &fun2; 
    	pf[2] = &fun3;
    	pf[0]("fun1");
    	pf[1]("fun2");
    	pf[2]("fun3");
    	
    	/**
    	 * 输出:
    	 *  fun1
         *  un2
         *  n3
         */
    	return 0;
    }
    

    结果

    结果
    或者使用函数指针声明成数组的形式。

    #include <stdio.h>  /* for printf */
    
    typedef char * (*Func)(char * p);
    
    char * funa1(char * p)
    {
    	printf("%s
    ", p);
    	return p;
    }
    char * funa2(char * p)
    {
    	printf("%s
    ", (p + 1));
    	return p;
    }
    char * funa3(char * p)
    {
    	printf("%s
    ", (p + 2));
    	return p;
    }
    int main()
    {
    	Func pf[3];
    	pf[0] = funa1;
    	pf[1] = funa2;
    	pf[2] = funa3;
    
    	pf[0]("Func0");
    	pf[1]("Func1");
    	pf[2]("Func2");
    	return 0;
    }
    

    结果如下
    运行结果

    注意事项

    • 赋给函数指针的函数应该和函数指针所指的函数原型(返回值, 参数一致)是一致的
    • 函数指针没有 ++ 和 -- 操作
  • 相关阅读:
    c#时间函数
    .NET中的lock(C#版本)
    关于OpenSmtp邮件标题过长,附件名,用户名出现乱码问题的终及解决Dll文件
    Windbg 用法
    使用OpenXML将数据导入到Excel模板中
    Compiere源码workspace的两个配置文件内容
    我学MEF系列(8):MEF+Unity实现可扩展拦截器
    基于插件架构的简单的Winform框架(上)
    我学Flash/Flex(2):AS3读取XML文件内容
    我学Flash/Flex(1):Action Script3.0基础知识
  • 原文地址:https://www.cnblogs.com/homejim/p/9996453.html
Copyright © 2011-2022 走看看