C语言中指向函数的指针

C语言中,如果想把函数A作为函数B的参数传递给B,那么就可以使用指向函数的指针。

假设我们有一个函数,来描述小动物一天的生活。包括吃、睡、叫。其中所有种类的动物的吃和睡方式都一样,但叫的不一样。可能会考虑下面的实现方式(不防假设只有3种动物):

#define CAT 1
#define DOG 2
#define WOLF 3

void liveoneday(int type)
{
	eat();
	sleep();
	
	if (type == CAT)
		catbark();
	if (type == DOG)
		dogbark();
	if (type == WOLF)
		wolfbark();
}

这样写有一个问题:每增加一种动物类型,都要去修改liveoneday的代码。 当然,还有另一个比较重要的问题,就是如果想把liveoneday做成一个通用的函数,不依赖于具体的动物类型,那么上面的写法就达不到目标,因为它的实现时是要判断动物类型的。为了解决这个问题,可以考虑使用指向函数的指针。将bark函数名作为参数传递给liveoneday(),在liveoneday内部,不需要考虑动物类型,传过来的是哪个bark函数,就调用哪个bark函数

#include <stdio.h>

#define CAT 1
#define DOG 2
#define WOLF 3

void dogbark(int barktimes);
void catbark(int barktimes);
void wolfbark(int barktimes);
void liveoneday(void (*bark)(int ));
void eat();
void sleep();

int main(void)
{
	int type;
	
	printf("Input animal type(1.Cat, 2.Dog, 3. Wolf):\n");
	scanf("%d", &type);
	
	switch (type) {
		case CAT:
			liveoneday( ( void (*)(int))(catbark) );
			break;
		case DOG:
			liveoneday( ( void (*)(int))(dogbark) );
			break;
		case WOLF:
			liveoneday( (void (*)(int))(wolfbark) );
			break;
		default:
			printf("No such animal\n");
			break;
	}

	return 0;
}

/*liveoneday: one day's life for any kind of animal*/
void liveoneday(void (*bark)(int ))
{	
	eat();
	sleep();
	(*bark)(3);
}

void eat()
{
	printf("I'm eating\n");
}

void sleep()
{
	printf("I'm sleeping..\n");
}

/*dogbark: dog bark barktimes*/
void dogbark(int barktimes)
{
	while ( barktimes-- )
		printf("Wang\n");
}

/*catbark: cat bark barktimes*/
void catbark(int barktimes)
{
	while (barktimes--)
		printf("Miao\n");
}

/*wolfbark: wolf bark barktimes*/
void wolfbark(int barktimes)
{
	while (barktimes--)
		printf("Ou..\n");
}

下面的声明表示liveoneday是一个函数,它没有返回值,需要一个参数。这个参数是一个函数:void (*bark)(int ),参数表示bark是一个指向函数的指针, 它指向的函数需要一个int类型的参数,并且没有返回值


    void liveoneday(void (*bark)(int ));

bark是一个指向函数的指针,所以*bark表示函数名,(*bark)(3)表示调用函数,并且调用时传递的参数为3(叫3声)

在主函数里,根据不同的动物种类,传递给liveoneday不同的bark函数指针。比如,如果是CAT,具体调用方式如下:


    liveoneday( ( void (*)(int))(catbark) );

liveoneday需要的参数是指向函数的指针,函数名本身就是函数的地址(犹如数组名本是就是数组的地址一样)可以简写:


    liveoneday( catbark );

再举另外一个例子,C标准库中有一个qsort函数,能实现对任意类型的数据进行排序。它实现的时候,没有判断数据的类型,而是使用了指向函数的指针,原型如下:


    #include <stdlib.h>
    void qsort( void *base, size_t n, size_t size, int (*cmp)(const void *, const void *) );


qsort函数对base[0]...base[n-1]数组中的对象进行升序排序,数组中每个对象的长度为size。在比较函数cmp中,若第一个参数小于第二个参数,返回负值。若相等,返回0。若第一个参数大于第二个参数,返回正值。

关于qsort的实现和更多关于指向函数的指针内容,可以参考《C程序设计语言》第二版5.11节。

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值