函数指针的好处、作用

14 篇文章 0 订阅

C中函数指针的作用  

项目中用到了很多封装在struct中的函数指针,以前在MFC里面经常用到则个作为回调函数,还以为是微软设计的特色呢。在网上查了一下它的用法,做个总结。

 
1)提供调用的灵活性。设计好了一个函数框架,但是设计初期并不知道自己的函数会被如何使用。比如C的”stdlib”中声明的qsort函数,用来对数值进行排序。显然,顺序还是降序,元素谁大谁小这些问题,库程序员在编写qsort的时候不可能决定。这些问题是要在用户调用这个函数的时候才能够决定。那边qsort如何保证通用性和灵活性呢?采用的办法是让函数的使用者来制定排序规则。于是调用者应该自己设计comparator函数,传给qsort函数。这就在程序设计初期保证了灵活性。尽管使用函数指针使得程序有些难懂,但是这样的牺牲还是值得的。
 
2)提供封装性能。有点面向对象编程的特点。比如设计一个栈结构

typedef struct _c_stack{
               int base_size;
               int point;
               int * base;
               int size;
               int  (*pop)(struct _c_stack *);
               int  (*push)(int,struct _c_stack *);
               int  (*get_top)(struct _c_stack);
}c_stack;

在初始化完之后,用户调用这个结构体上的pop函数,只需要s.pop(&s)即可。即使这个时候,工程内部有另外一个函数名字也叫pop,他们之间是不会发生名字上的冲突的。

原因很简单,因为结构体中的函数指针指向的函数名字可能是

int ugly_stupid_no_one_will_use_this_name_pop(c_stack *)
,只是stack的用户是不知道他在调用s.pop(&s),实际上起作用的是这样一个有着冗长名字的函数。

 函数指针这种避免命名冲突上的额外好处对于一些库函数的编写者是很有意义的,因为库可能被很多的用户在许多不同的环境下使用,这样就能有效的避免冲突而保证库的可用性。


2012-07-07 15:35  912人阅读  评论(0)  收藏  举报

一般的时候用不到,主要还是一个简化结构和程序通用性的问题,也是实现面向对象编程的一种途径。简单的总结为:

1.       实现面向对象编程中的多态性

2.       回调函数


举两个例子:
1. 你现在要实现一个文件系统,但是文件的介质有硬盘和软盘,那么它们各自的读写函数实现肯定是不一样的。
好比  
int a_write(char *data_stream, int LBA);
int b_write(char *data_stream, int LBA);
有一个结构体维护:
typedef int (*write_operation)(char* data, int LBA);
struct {
  write_operation op;
  ...
} file_struct;
最后有一个写函数:
int file_wirte(char *data_stream, int LBA)
{
  return file_struct.op(data_stream, LBA);
}

2. Windows编程中的事件handle函数,即回调函数,在事件队列都是一个函数指针来保存的:
typedef void (*event_handler) (unsigned int para1, unsigned int para2);
struct event {
  unsigned int ev_id;
  event_handler handler;
};

struct event event_queue[MAX_EVENT_SIZE];
程序可以通过扫描这个事件队列来获取每个事件对应的处理函数,然后调用它,即为回调函数。


求解释c语言函数指针的作用

举报|2012-05-11 13:39 823807  |  分类:C/C++  |  浏览1428次
使用函数指针的好处在于,可以将实现同一功能的多个模块统一起来标识,这样一来更
容易后期的维护,系统结构更加清晰。或者归纳为:便于分层设计、利于系统抽象、降低耦合度以及使接口与实现分开

我是初学者,不明白这段话什么意思,求解释
2012-05-11 14:27 提问者采纳
你上面那一段话,对于初学者来说确实坑爹,说的像什么官方话语,我看着也就只能理解个模糊大概。
先给你举个例子吧,函数指针的写法
int *p;
int a;
p=&a; //这是一般整型指针
#include <iostream>
using namespace std;
int arr(int a,int b){return 0;}//比如说是函数1
int brr(int a,int b){return 1;}//比如说是函数2
int main()
{
   int (*frr)(int,int); //这里就是函数指针
	frr =arr; //它可以指向arr
	cout<<frr(1,2)<<endl;
	frr=brr;//也可以指向brr,只需要改改指向的对象,就可以操作不同的函数
	cout<<frr(1,2)<<endl;
	return 0;
}
评论 | 12 0

qincheng2007 |来自团队美女也开源吧 |七级采纳率49%

擅长:C/C++

按默认排序|按时间排序

其他2条回答

2012-05-11 14:57 copylegend |五级
好吧,假设你已经知道函数指针的写法和用法。
那么那段话的意思就是, 你有了一只手,可以用来装备并切换武器打怪,比如可以装备刀子,或者装备棍子。当你的武器只有一种或者比较少的时候,可能这只手切换武器的功能不常用到。当到了后期,你的武器多了,那你因为有了这只能装备并切换武器的手,而可以更有效率的打怪。
OVER
评论(1) | 7 0
2012-05-12 11:20 刘嘉璠 |四级
上面的话是有道理的。只是,要真的体会这些名词,需要你亲历躬行,一个“百度知道”是很难让你真正体会并理解的。国人一些教科书也不负责任,人云亦云的说这些话,但很少能透彻讲解。我小试一下。

1. 便于分层设计:函数指针是引用,是间接层,或曰隔离层。它输出到上层,给上层用户用。函数实体是实现,在下层,给开发者用,实现者(软件工程师)关注。这就是简单的分层的概念了。上层用户想让一个函数所做的东西会变化时,我们只需要改变底层实现,并用函数指针指向新的实现就行了。
再精炼一下分层:分层的核心是对接口进行设计和实现。函数指针的作用就是提供不同实现的统一接口。
2. 利于系统抽象:只有存在多个类似的实体需要模拟、操作或控制时(这种情况很多)才需要抽象。多个类似的实体就是对象,抽象的结果就是类。在C里边,可以用函数指针数组完成这种抽象。如, fopen 就是一个例子。他可以打开文件。C里面将磁盘文件、串口、USB等诸多设备抽象为文件。
3. 降低耦合度以及使接口与实现分开:第1条中的解释已经说明了这一点。
再具体一下:
我曾搭建过一个嵌入式平台。其中的设备操作(硬件驱动)采用了多组函数指针数据,并进行了简单的封装,其结果是:
业务软件使用函数指针数组的封装函数访问设备。这个封装可展示为:
int  DevOpen(char *strDevName);
int  Write(int DevID, char* DataFrom, int StartDevAddr, int  DataLong);
int  Read(int DevID, char* DataTo, int StartDevAddr, int  DataLong);
int  DevClose(int DevID);

这组抽象出来的函数,是一组语义清晰且稳定的上层接口,为上层的业务开发团队使用。底层的驱动层,各自实现自己的设备打开、读、写及关闭代码,然后,注册自己的设备到系统列表里。上层业务接可以使用了。期间的耦合在这里:
int  Write(int DevID, char* DataFrom, int StartDevAddr, int  DataLong)
{
     /* Error detecting.  */
      return DevWrite[ DevID ]( char* DataFrom, int StartDevAddr, int  DataLong );
}

其中,DevWrite[ DevID ]就是一个函数指针数组:
int  (*DevWrite)[ MAX_DEV_NUM ]( char*,int,int ) = {0};
里面放的就是多个设备的写的操作。其中包括:UART,RTC,WatchDog。EEPROM,DigitalInput,DigitalOutput,Key,LCD,LED。
好了。说的太多了。如需要学习,可邮件livefuture@163.com。
但愿对你有所帮助。


指向函数的指针变量作为函数参数有什么好处?

举报|2008-02-04 14:24 13152448536  |  分类:其他编程语言  |  浏览2313次
书上给了个例子,但还是看不懂有什么好处?
#include<stdio.h>

float add(float x,float y)
{return (x+y);}
float sub(float x,float y)
{return (x-y);}
float mul(float x,float y)
{return (x*y);}
float div(float x,float y)
{return (x/y);}

float result(float x,float y,float(*pf)(float,float))
{
    float s;
    s=(*pf)(x,y);
    return s;
}

void main()
{
    float a,b,s;
    char op;
    printf(""please select your operation (input +,-,*or/)\n");
    scanf("%c",&op);
    printf("please input the two operand\n");
    scanf("%f %f",&a,&b);
    switch(op)
   {
    case '+':s=result(a,b,add);break;
    case '-':s=result(a,b,sub);break;
    case '*':s=result(a,b,mul);break;
    case '/':s=result(a,b,div);break;
    }
    printf("the operation is :%f%c%f=%f\n",a,op,b,s);
}
2008-02-04 23:02 提问者采纳
灵活。
实际上我觉得如果作参数不用指针的话,还真不知道怎么解决。
参数传递一般就是传值和传址两种方式,作为函数的话,好像都想不出怎么传值。
我理解所谓指向函数的指针就是这个函数的入口地址。直接就跳转到那个地址去执行了。



  • 34
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值