作者能力有限。 如果文章有什么不对的地方,还请朋友们及时指出。 我将非常感激。 谢谢你!
1.跳表的概念
引用作者看到的跳转表的概念:
在 中,表或跳转表是使用 of 或跳转表对 a(或可能已经存在)的一部分进行 of () 的操作。
大致意思是跳转表,或者分支表,是一种利用分支或者跳转指令表将程序控制权转移到程序的另一部分(或者已经动态加载的其他程序)的方法。
跳转到程序另一部分的最常见方法是使用语句。 然而,using 语句的一个缺点是,如果分支太多,程序就会变得冗长。 跳转表正好可以解决这个问题,对于优化程序的结构有很大的帮助。
在介绍跳转表之前,本文首先介绍一下跳转表涉及到的指针数组和函数指针的概念。
2. 指针数组
首先,它是一个数组,数组的元素是指针。 假如有一个指针数组的定义如下:
int*p1[5];
那么,可以用下图来说明其含义:
3.函数指针
函数指针的含义如其名称所示。 它是一个指针,一个函数的指针,指向一个函数。 例如,下面我们可以定义一个函数指针变量。
int(*pf)(int,int);
上面的指针变量表示定义了一个pf的函数指针变量。 这个指针变量可以指向一个返回值为int、有两个int类型参数的函数。 假设现在我们有一个这样的函数来添加两个数字:
int add(int num1,int num2);
然后,我们可以通过将函数指针变量指向该函数来调用该函数,例如:
pf = add;
pf(5,8);
以上是对函数指针的简单说明。
4. 跳转表
引入指针数组和函数指针后,我们可以构建我们的跳转表,如下所示:
void(*pf[])(void) = {fna,fnb,fnc,fnd};
其中,fna、fnb、fnc、fnd都是返回值和参数均为void的函数。 上面定义的函数跳转表意味着有一个函数指针数组,所有的函数指针都存储在这个数组中。
之所以称为跳转表,是因为可以通过索引来调用函数。 以下是定义上述传输表后的应用:
void test(constint jump_index)
{
pf[jump_index]();
}
下图形象地表达了跳表的原理:
通过调用不同参数的测试函数,可以通过测试运行不同函数的功能。 试想一下,如果用这里使用的方法来实现上述功能,代码量是不是会多很多呢?
5. 举个例子
下面的例子是笔者在国外网友的帖子中看到的,不过该网友并没有提供全部代码,缺少一些更多的细节,但是并不影响我们的理解。
背景:有一个工业电源接口盒,使用简单的ASCII码助记符作为命令。 接口盒通过输入命令进行相关操作,并通过RS-232接口返回输入的参数值。
从后台我们可以知道,我们需要定义一个数组存储命令。 代码如下:
staticconstchar read_str[] =
"0SV0SN0MO0WF
1ST1MF1CL1SZ
2SP2VO2CC2CA";
由于后台需要返回参数并通过RS-232串口传输,因此输入命令后跳转执行的函数有以下返回值和形式参数。
constchar*fna(void);
另外,这个函数声明意味着函数值类型为const char *,形参为void,返回值类型也对应我们刚才定义的。
综上所述,我们可以定义我们的跳转表。 跳转表定义如下:
staticconstchar*
(*readfns[sizeof(read_str)/4])(void) =
{
/*这里是伪代码,因为命令太多,所以这样进行表示*/
una,fna,fnb,...
}
una、fnb等都是与fna同一类型的函数。 说到这里,比较关键的代码就写完了。 以下是整个处理过程的代码:
constchar*fna(void);
staticvoid process_read(constchar*buf)
{
char*cmdptr;
unsignedchar offset;
constchar*replyptr;
staticconstchar read_str[] =
"0SV0SN0MO0WF
1ST1MF1CL1SZ
2SP2VO2CC2CA";
staticconstchar*
(*readfns[sizeof(read_str)/4])(void) =
{
/*这里是伪代码,因为命令太多,所以这样进行表示*/
una,fnb,fnc,...
}
/*cmdptr获得的是当前输入字符的地址*/
cmdptr = strstr(read_str,buf);
if(cmdptr != NULL)
{
/*(当前地址 - 数组基地址)/4 = 索引*/
offset = (cmdptr - read_str) / 4;
replyptr = (*readfns[offset])();
}
}
上面函数的作用是返回输入字符串与数组中的字符串匹配的元素的地址。 最后根据索引值调用相应的函数,这样也就实现了后台描述的根据输入命令执行相应操作的功能。 如果命令很多,可想而知代码会有多长。
六、总结
上面的例子清楚地展示了跳转表在优化代码结构方面的强大作用。 如果有一组函数对应的操作具有相同的函数返回值和相同的形参,则应该考虑使用跳转表。 会帮助你写出漂亮的代码。
结尾