C函数指针应用之转移表(jump tables)
来源:互联网 发布:阿里云 专线 编辑:程序博客网 时间:2024/06/09 13:47
简介
函数指针是指向函数的指针变量。 因而“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。
函数指针的应用最多的是转移表(jump table)和回调函数(callback function)
使用转移表可以替代冗长的switch和if-else语句,分离了具体操作和选择代码,是一种良好的设计方案。和其他指针一样,对函数指针执行间接访问之前,必须把它初始化并指向某一个函数。
详解
下面举一个例子说明什么是转移表:
Q:编写一个程序,从标准输入读取一串字符,根据ctype.h中函数定义的字符分类,计算各类字符所占的百分比。不能使用一系列If语句。
Solution:
事实上转移表就是一个函数指针数组,声明并初始化一个数组
确保函数原型出现在这个数组声明之前,在使用转移表这个指针数组时特别要注意下标引用不要越界,否则会引起不可预知的后果。
函数在被使用时总是由编译器把它转换为函数指针。
接着我们就能用这个转移表来替换switch和if了。
int isnotprint(int c){if(isprint(c))return FALSE; return TRUE;}/*jump table of chartest,each function return none-zero or FALSE*/int (*chartest[])( int )={ iscntrl, isspace, isdigit, islower, isupper, ispunct, isnotprint};完整的代码:
#include<stdio.h>#include<stdlib.h>#include<ctype.h>#define TRUE 1#define FALSE 0#define MAX_LINE_LENTH 1024 /*define the max buffer*/#define ENUMVERSION 0int isnotprint(int c){if(isprint(c))return FALSE;return TRUE;}/*jump table of chartest,each function return none-zero or FALSE*/int (*chartest[])( int )={iscntrl,isspace,isdigit,islower,isupper,ispunct,isnotprint};#define N_CATEGORIES\(sizeof(chartest)/sizeof(chartest[0]))/*使用这种宏,能使代码段更具可拓展性*/#if ENUMVERSIONtypedef enum{cntrl,space,digit,lower,upper,punct,print}charType;#endif /*ENUM VERSION ONLY*//*printing label*/char* label[]={" control"," space"," digit"," lower letter"," upper letter"," punct letter"," unprinted letter"};int main(){char buffer[MAX_LINE_LENTH],*str;//声明缓冲区float num[7]={0,0,0,0,0,0,0};//用于记录各种字符数量的数组float sum=0;//字符总数 int i; printf("Please input the string:\n"); str=fgets(buffer,MAX_LINE_LENTH,stdin);//从标准输入读取一串字符if(str==NULL){exit(1);//如果失败} /*判断字符种类,使用转移表和循环代替switch和if*/ while( (*str++)!='\0' ){++sum;for(i=0;i<N_CATEGORIES;i++){if(FALSE!=chartest[i](*str)) ++num[i];}} printf("the total character number:%3f\n",sum); for(i=0;i<N_CATEGORIES;i++){printf("the%s count:%3f %3f%%\n",label[i],num[i],100*num[i]/sum);}return 0; }
技巧
在这里使用了一个宏:
#define N_CATEGORIES\(sizeof(chartest)/sizeof(chartest[0]))
使用这样一个宏计算转移表的长度,在使用转移表的时候,这个宏可以作为循环条件,一定程度上,改善了代码的易扩展性
在从标准输入输入一串字符串的时候,用的是fgets而不是gets,原因是gets函数并没有指定缓冲区长度,这个函数只能用于玩具程序,使用fgets更为安全。
- C函数指针应用之转移表(jump tables)
- c和指针之转移表 demo
- C语言函数指针与转移表的用法技巧
- C语言中,函数指针数组的用途:转移表
- 函数指针与转移表
- C语言指针笔记之 一级指针的应用(指针做函数参数)
- C/C++用状态转移表联合函数指针数组实现状态机FSM
- C-[之函数指针]
- C函数指针应用之回调函数
- [C++] 函数指针的应用
- 《C和C指针》中转移表的实现
- Jump Tables via Function Pointer Arrays in C/C++
- 函数指针实现转移表代替switch语句
- 转移表——函数指针数组+枚举
- 通过转移表练习函数指针的使用
- C指针编程之道(二)- 指针与函数
- c语言之函数指针
- C常见问题之函数指针
- c#-sql之having
- Solr分页查询代码,包含查询,分页,高亮及获取高亮处摘要代码
- 动态规划:从新手到专家(在网上看到的一篇将动态规划很详细的文章)
- android 加密 SO 破解
- Metasploit 整理笔记
- C函数指针应用之转移表(jump tables)
- 脚本语言中“脚本”是什么含义
- IPC机制 基础知识
- 弯道超车:容器技术究竟为云计算带来了什么?
- Ubuntu下相关软件的安装
- 自己动手丰衣足食之tab选项卡(第一个可拓展轮播图)
- 【慕课笔记】第二章 认识JAVA中的字符串 第4节 JAVA中String类的常用方法(二)
- ACM_欧几里得(GCD) 扩展欧几里得(EXGCD)
- 《VR入门系列教程》之15---配置Oculus的开发环境