一、函数指针
1、定义
顾名思义,函数指针就是函数的指针。它是一个指针,属于一个数据类型,其指向一个函数。如定义一个函数,其入口地址就是这个函数的指针,是个常量,可以用该常量给函数指针类型的变量赋值,如下:
void (*p_fun)();//定义函数指针变量
void fun()
{
//空函数;
}p_fun = fun;//给变量赋值
p_fun = &fun;//这样的写法也认可
2、使用例子
如下,函数指针的简单使用,
#include <stdio.h>
int sum(int a,int b)
{return a+b;
}
int main()
{int sum1,sum2;int (*fun)(int x,int y);fun = sum;sum1 = (*fun)(1,2);sum2 = sum(1,2);printf("%d,%d",sum1,sum2);return 0;
}
其执行的结果为:
3,3
可以看出其结果一致,在使用函数指针时,通过用(*fun)取出存在这个地址上的函数,然后调用它。
上面的例子比较简单,再看看下面的使用:
void Fun()
{printf("hello world!\n");
}int main()
{void (*p)();*(int*)&p=(int)Fun;(*p) ();return 0;
}
首先,void (*p)();这句代码定义了一个指针变量p,其指向一个函数,这个函数的参数和返回值都是void。&p是求指针变量的地址(即地址的地址),(int *)&p表示将地址强制转换成指向int类型数据的指针,*(int*)&p=(int)Fun则表示,将函数的入口地址赋值给指针变量p。之后便于上面例子相同了。
下面,再来看一个比较复杂的,其在单片机的固件中使用较多,
(*(void(*) ())0)();
这是《C Traps and Pitfalls》这本经典的书中的一个例子。下面来逐步分析,第一步:void(*) (),可以明白这是一个函数指针类型。这个函数没有参数,没有返回值。第二步:(void(*) ())0,这是将 0 强制转换为函数指针类型,0 是一个地址,也就是说一个函数存在首地址为 0 的一段区域内。第三步:(*(void(*) ())0),这是取 0 地址开始的一段内存里面的内容,其内容就是保存在首地址为 0 的一段区域内的函数。第四步:(*(void(*) ())0)(),这是函数调用。好像还是很简单是吧,上面的例子再改写改写:(*(char**(*) (char **,char **))0) ( char **,char **);看不懂了就是参考这里
3、函数指针数组
欲将多个函数指针在内存中连续的放在一起,就可以定义为一个函数指针数组。如下:
char * (*p_fun[3])(char * p);
void fun1(void)
{printf("1\n");
}
void fun2(void)
{printf("2\n");
}
void fun3(void)
{printf("3\n");
}
int main()
{void (*pf[3])();pf[0] = fun1; // 可以直接用函数名pf[1] = &fun2; // 可以用函数名加上取地址符pf[2] = &fun3;pf[0]();pf[1]();pf[2]();return 0;
}
二、指针函数
指针函数, 即返回值为指针的函数, 实质上是一个函数。如:
int * fun(void);
char * fun(int a);
void * fun(char * a,char * b);
所谓的指针函数也没什么特别的,和普通函数对比不过就是其返回了一个指针(即地址值)而已。
例如,求最大值函数(指针作为函数的返回值)
#include <stdio.h>
int *max(int *p1, int *p2)
{if(*p1 > *p2)return p1;else return p2;
}
int main()
{int *p, a, b;a = 1; b = 2;p = max(&a, &b);printf("%d\n", *p);return 0;
}