首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

抛砖引玉,函数指针数组的现实用途

2013-03-06 
抛砖引玉,函数指针数组的实际用途函数指针数组是个比较复杂的概念,会用的人不多,CSDN上相关的问题也很少。

抛砖引玉,函数指针数组的实际用途
函数指针数组是个比较复杂的概念,会用的人不多,CSDN上相关的问题也很少。从概念上分析,函数指针数组首先是一个数组,数组的元素都是函数指针,而函数指针又是一个指针,但它不是指向普通数据类型或者结构体的指针,而是一个指向函数的指针。

我的问题是,函数指针数组在实际开发中,都有些什么用途?其实,不使用函数指针数组,大部分情况都是可以使用别的方法完成的。以大家的经验和体会,是怎样灵活使用函数指针数组以提高程序的可读性和执行性能的?最好能给出代码实例。

[解决办法]
下面例子是来自我写的一篇文章,感兴趣的话可以去看看,这只是C语言应用的一个小小的技巧,其中对于一长串switch,函数指针数组也是一种选择。


#ifndef _TEST_C_

#define _TEST_C_

 

#include <stdio.h>

 

int _my_add(int,int);

int _my_sub(int,int);

int _my_mul(int,int);

int _my_div(int,int);

int _my_mod(int,int);

 

int main(void)

{

       int number_one;

       int number_two;

       int number_control;

 

       int (*function_buffer[])(int,int) = {

              _my_add,_my_sub,

              _my_mul,_my_div,

              _my_mod

       };

 

    while(1)

       {

              printf("这是一个简单的计算器,主要有下面的功能!\n");

              printf("    1:加\n     2:减\n     3:乘\n     4:除\n     5:求模\n");

              printf("输入格式为:num1 num2 操作\n");

 

              scanf("%d %d %d",&number_one,&number_two,&number_control);

 

    if(((number_control == 4) &&(!(number_two 
[解决办法]
 0x0)))\

                     
[解决办法]
 (number_control > 5)){

                     printf("input is err\n");

                     continue;

              }

 

 

              printf("Result is:%d\n",\

                       function_buffer[number_control - 1](number_one,number_two));

       }

 

       return 0;

}

 

int _my_add(int number_one,int number_two)



{

       return number_one + number_two;

}

 

int _my_sub(int number_one,int number_two)

{

       return number_one - number_two;

}

 

int _my_mul(int number_one, int number_two)

{

       return number_one * number_two;

}

 

int _my_div(int number_one, int number_two)

{

       return number_one / number_two;

}

 

int _my_mod(int number_one,int number_two)

{

       return number_one % number_two;

}

 

#endif


[解决办法]
函数指针的简单举例
#include<stdio.h>
#include<stdlib.h>
void menu()
{
    printf("***************************\n");
    printf("****1,显示所有记录    ****\n");
    printf("****2,按总分降序排序 ****\n");
    printf("****3.增加一条记录    ****\n");
    printf("****4.删除指定记录    ****\n");
    printf("****0.退出             ****\n");
    printf("****************************\n");
    return ;
}
bool showall()
{
    printf("成功显示\n");
    return 1;
}
bool paixu()
{
    printf("排序OK\n");
    return 1;
}
bool add()
{
    printf("成功添加了一条记录\n");
    return 1;
}
bool del()
{
    printf("删除OK\n");
    return 1;
}
bool quit()
{
    exit(0);
    return 1;
}
bool (*func[])()=  //请注意格式
{
    quit,//
    showall,
    paixu,
    add,
    del
};   //
int main()
{
    int selected=0;
    bool flag=true;
    menu();
    do
    {
        printf("\n请选择你要进行的操作.\n");
        scanf("%d",&selected);
        func[selected]();
    }while(flag);
    return 0;
}

[解决办法]
优点一:编码美观,容易维护

typedef void (*FUN)();
//事件类型
enum EVENT_TYPE
{
EVENT_TYPE_1 = 0,
EVENT_TYPE_2,
EVENT_TYPE_3,
EVENT_TYPE_END,
};
//这里不是单纯的函数指针,稍微扩展成了一个STRUCT,为了阅读,维护更容易
struct EVENT_FUN_MAP
{
EVENT_TYPEeType;
FUNpFun;
};
//针对不同的事件,只需要修改这个就可以改变事件的动作
EVENT_FUN_MAP eFunMap[EVENT_TYPE_END] = {
EVENT_TYPE_1,&EventFun1,
EVENT_TYPE_2,&EventFun2,
EVENT_TYPE_3,&EventFun3,


}

..............................

void DoAction(EVENT_TYPE eType)
{
(*eFunMap[eType].pFun)();
}


优点二:容易动态重载,某些事件有默认处理函数,只需要重载某些自定义的处理函数

void DoAction(EVENT_TYPE eType)
{
(*eFunMap[eType].pFun)();
}

void ReloadEventFun()
{
eFunMap[EVENT_TYPE_1].pFun = &MyEventFun1;
}

再举个实际例子,WINDOWS驱动编程中的DriverEntry函数(类似于main函数)就是通过重载事件(IRP)来实现驱动的特定事件处理。

#pragma INITCODE
extern "C" NTSTATUS DriverEntry (
IN PDRIVER_OBJECT pDriverObject,
IN PUNICODE_STRING pRegistryPath) 
{
NTSTATUS status;
//注册其他驱动调用函数入口
pDriverObject->DriverUnload = HelloDDKUnload;
pDriverObject->MajorFunction[IRP_MJ_CREATE] = MyDDKCreate;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = MyDDKClose;
pDriverObject->MajorFunction[IRP_MJ_WRITE] = MyDDKWrite;
pDriverObject->MajorFunction[IRP_MJ_READ] = MyDDKRead;
.........
        .........
}


另外,扯远点,C++里多态函数的实现是靠虚表指针,而虚表指针所指向的就是一个函数数组(当然和这些应用是有区别的),MFC里的消息映射使用的也是函数数组指针
[解决办法]
#include <stdio.h>

struct Fucker_
{
#define MAX_LIST 256
int top;
void (*FuckEvent[MAX_LIST])(struct Fucker_* pThis);
};
typedef struct Fucker_ Fucker;
voidinit(Fucker* pThis)
{
pThis->top = 0;
}
voidpush(Fucker* pThis, void (*pHandler)(Fucker* p))
{
pThis->FuckEvent[pThis->top++] = pHandler;
}
voidpop(Fucker* pThis)
{
--pThis->top;
}
voiddo_fuck(Fucker* pThis)
{
int i;
for (i = 0; i < pThis->top; ++i)
(*pThis->FuckEvent[i])(pThis);
}
voidPolice(Fucker* pThis)
{
puts("catch him");
}

voidPeople(Fucker* pThis)
{
puts("come on");
}

int main()
{
Fucker a;
init(&a);
push(&a, Police);
push(&a, Police);
push(&a, People);
do_fuck(&a);
pop(&a);
do_fuck(&a);
return 0;
}

[解决办法]
static intSet[COMMAND_NUMBERS]=
{
'AA','AC','AD','AR','AT',
'BP',
'CF','CI','CP','CR','CT',
'DC','DF','DI','DL','DP','DR','DT','DV',
'EA','EC','EP','ER','ES','EW',
'FI','FN','FP','FR','FT',
'IN','IP','IR','IW',
'LA','LB','LO','LT',
'MC','MG','MT',
'NP','NR',
'OD','OE','OH','OI','OP','OS',
'PA','PC','PD','PE','PG','PM','PR','PS','PU','PW',
'QL',
'RA','RF','RO','RP','RR','RT',
'SA','SB','SC','SD','SI','SL','SM','SP','SR','SS','ST','SV',
'TD','TR',
'UL',
'VS',
'WG','WU'
};
int InSet()
{
//wat
key=toupper(ch2)
[解决办法]
(toupper(ch1)<<8);
//bc3
//key=toupper(ch1)
[解决办法]
(toupper(ch2)<<8);
n=COMMAND_NUMBERS;
SetInUse=Set;
if (PictureBodyState==YES&&LostMode==OFF) SetInUse=SetBody;
else if (PolygonMode==ON &&LostMode==OFF) SetInUse=SetPoly;


else if (PolygonMode==OFF&&LostMode==ON)  SetInUse=SetLost;
else if (PolygonMode==ON &&LostMode==ON)  SetInUse=SetLostPoly;
CommandIndex=(int *)lfind(&key,SetInUse,&n,sizeof(int),(int(*)(const void *,const void *))compare);
if (CommandIndex) return YES;
else return NO;
}
//-------------------------------------------------------
if (InSet()) {
((void(*)())CommandEnterPointTable[(FP_OFF(CommandIndex)-FP_OFF(SetInUse))/sizeof(int)])();
//ignore CR,LF,SPC,Parameters that not need
do ch1=GetAChar(); while (!(isalpha(ch1)
[解决办法]
feof(fi)
[解决办法]
ch1==27));
if (feof(fi)) break; else continue;
} else {
ch1=ch2;
ErrorNumber=1;
ReportError();
continue;
}
CommandEnterPointTable[ 0]=(unsigned long)AA;
CommandEnterPointTable[ 1]=(unsigned long)AC;
void AA();
void AC();

热点排行