深入理解函数指针

指针型函数:函数类型   *函数名(形参定义表)

int   *fun(int x, int y)

函数指针:函数类型  (*函数指针名)(形参表)

int   (*fun) (int x, int y)

函数指针数组:函数类型  (*函数指针名[数组元素个数])(形参表)

int   (*fun [10]) (int x, int y)

上面是定义了一个指针数组,数组元素为函数指针

 

下面有几个问题可以更好的理解

问1:声明一个指向含有10个元素的数组的指针,其中每个元素是一个函数指针,该函数的返回值是int,参数是int*

第一步:定义返回值是int,参数是int*的函数指针pf为int (*pf) (int *)

第二步:含有10个元素的数组的指针p为int (*p)[10]

最后:合成为

int (*(*p)[10]) (int *)

问2:定义一个函数指针,指向的函数有两个int形参并返回一个函数指针,返回的指针指向一个int形参且返回int的函数

第一步:定义指向的函数有两个int形参并且返回为Type类型的函数指针,为Type (*pf) (int, int)

第二步:返回值为int *,参数为int的函数,为int *f(int)

最后:合成为

int (*(*F)(int, int)) (int)

问3:定义一个函数指针,指向的函数的返回值为一个函数指针数组(数组元素为返回值为int,参数为int *的函数指针),参数为int *

第1步:返回值的元素为       int (*s)(int)
第2步:指针数组为              int (*p)[10]
合并为:                              int (* (*p)[10] )(int) 
第3步:指针函数的参数类型为 int (*f)(int)

最后合成:

int (*  (*  (p)(int*)  )[10]  )  (int *);

问4:下面的定义是啥意思

void (*func(void (*p)(void *), void *x)) (void *);

相信读者应该了解了我就不解释了

 

函数指针的一般用法是:

void (* fun)(void);  //定义函数指针
fun = (void (*)(void)) 0x12345678  //将地址强制转换为函数类型地址
(*fun)();   //运行地址上的函数

实例代码:

#include <stdio.h>

void fun1(void *x)
{
	printf("%d \n", *((int *)x));
}

void fun2(void *y)
{
	printf("%g \n", *((double *)y));
}

void (*func(void (*p)(void *), void *x)) (void *)
{
	(*p)(x);        //执行P指向的函数,输出2
	return fun2;   //返回fun2函数地址
}

int main()
{
	int x = 2;
	double y = 1.25;
	void *px = &x;
	void *py = &y;
	void (*pf) (void *);
	pf = func(fun1, px);
	(*pf)(py);   //执行fun2  ,输出1.25
	return 0;
}

运行结果:
2
1.25

关于typedef的函数指针

在实际项目中,一般用typedef来产生新类型,那就和上面的情况有些不同。可能你了解了上面的内容,但是还是不能很好的完成下面的文题。

这里有几个问题:下面的语句是什么意思?如何声明或定义才使它们更易懂?

int (*foo())();
int (*(*foo)())();
int (*foo())[]; 
int (*foo[])(); 
(*(void(*)())0)(); 
void (*signal(int,void(*)(int)))(int); 

问题1:int (*foo())();
眨眼一看,你可能以为是一个函数变量,其实它是一个函数声明,等价于:

typedef int (*pf)();
pf foo();

pf foo();这段代码,如果没有上面的提示,可能以为是定义一个变量,但其实是声明。

问题2:int (*(*foo)())();

这个就是定义了一个指针,等价于:

typedef int (*pa)();
int (*(*p)())();

//给指针赋值
pa fun()
{
    pa a;
    printf("fun\n");
    return a;
}
p = fun;
p();  //运行fun

问题3:int (*foo())[];
也是一个函数声明,等价于:

typedef int (*pa)[];
pa foo();

问题4:int (*foo[])();
声明一个数组,等价于:

typedef int (*pf)();
pf foo[];

问题5:(*(void(*)())0)();
这是一个函数调用,等价于:

typedef void (*pf)();
pf pF = 0;
(*pF)();

问题6:void (*signal(int,void(*)(int)))(int);
也是一个函数声明,等价于:

typedef void (*pf)(int);
pf signal(int, pf);

 

注意:

数组元素不能是函数变量,只能是函数指针变量
返回值不能是函数变量,只能是函数指针变量

    int ( a[10]) (int);   //错:数组元素不能是函数变量
    int (*a[10]) (int);

    int ( (*p)[10]) (int);//错:数组元素不能是函数变量
    int (*(*p)[10]) (int);

    int ( (*p)(int))(int);//错:返回值不能是函数变量
    int (*(*p)(int))(int);

总结:

没有函数变量,只有函数声明,函数指针和函数定义。

万变不离其宗,函数指针只要搞清楚,返回值问题,函数声明问题,函数指针数组问题,再复杂的问题都是由这几个问题引伸出来的。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值