函数指针

@

函数指针

定义

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

声明

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

比如

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\n", sum);
    
    // Use standard library function 'cos()' as the pointed-to function
    sum = compute_sum(cos, 0.0, 1.0);
    printf("sum(cos): %g\n", sum);

    // Use user-defined function 'square()' as the pointed-to function

    sum = compute_sum(square, 0.0, 1.0);
    printf("sum(square): %g\n", 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\n", p);
	return p;
}
char * fun2(char * p)
{
	printf("%s\n", (p+1));
	return p;
}
char * fun3(char * p)
{
	printf("%s\n", (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\n", p);
	return p;
}
char * funa2(char * p)
{
	printf("%s\n", (p + 1));
	return p;
}
char * funa3(char * p)
{
	printf("%s\n", (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;
}

结果如下
运行结果

注意事项

  • 赋给函数指针的函数应该和函数指针所指的函数原型(返回值, 参数一致)是一致的
  • 函数指针没有 ++ 和 -- 操作
posted @ 2018-11-21 17:28  阿进的写字台  阅读(480)  评论(0编辑  收藏  举报