请给我一些跳转表用法的例子。我在维基百科上看过这个例子:
#include <stdio.h>
#include <stdlib.h>
typedef void (*Handler)(void); /* A pointer to a handler function */
/* The functions */
void func3 (void) { printf( "3\n" ); }
void func2 (void) { printf( "2\n" ); }
void func1 (void) { printf( "1\n" ); }
void func0 (void) { printf( "0\n" ); }
Handler jump_table[4] = {func0, func1, func2, func3};
int main (int argc, char **argv) {
int value;
/* Convert first argument to 0-3 integer (Hash) */
value = atoi(argv[1]) % 4;
if (value < 0) {
value *= -1;
}
/* Call appropriate function (func0 thru func3) */
jump_table[value]();
}
但是我想知道是否有另一种方法来调用函数而不是如图所示使用索引,在上面的例子中它是jump_table[value]();
我想要实现的是,不是使用索引,而是使用函数本身的名称。
例如,假设我们在结构中有所有函数指针。
typedef struct _funcptrs
{
void func1();
void func2();
} funcptrs;
现在,当我想调用该函数时,我可以执行类似funcptrs.func1()
的操作吗?
答案 0 :(得分:9)
您当然可以创建一个包含函数指针的struct
。甚至有充分的理由这样做。
举一个例子,考虑操作系统和某种设备驱动程序之间的接口。简化很多,这可能看起来像这个顺序:
struct device {
int (*open)(unsigned mode);
int (*close)(void);
int (*read)(void *buffer, size_t size);
int (*write)(void *buffer, size_t size);
};
然后,单个设备驱动程序将创建此类型的结构,并初始化各个指针以引用与特定设备相关的功能:
struct device serial_port = {
open_serial,
close_serial,
read_serial,
write_serial
};
struct device ethernet_adapter = {
open_net,
close_net,
read_net,
write_net
};
struct device keyboard = {
open_keyboard,
close_keyboard,
read_keyboard,
NULL // we'll assume no writing to the keyboard...
};
然后,某些更高级别的功能可以接收其中一个,并打开/关闭/读取/写入某个设备,而无需知道所涉及设备的确切身份。当然,对于真正的操作系统来说,它比这更复杂,但总体思路是(或者至少可以)非常相似。
答案 1 :(得分:5)
当然,但是你需要将它们声明为函数指针并首先初始化它们。如果你必须拼出函数名称,这会破坏跳转表的目的。
e.g。
#include <stdio.h>
void func1 (void) { printf( "1\n" ); }
void func0 (void) { printf( "0\n" ); }
typedef struct
{
void (*func0)(void);
void (*func1)(void);
} funcptrs;
int main(int argc, char *argv[])
{
funcptrs funcs = { func0, func1 };
funcs.func1();
return 0;
}
如果需要通过将函数名称作为字符串来调用函数,则需要在函数名称和函数指针之间创建映射,然后在表中搜索该函数,并调用它。
#include <stdio.h>
#include <string.h>
void func1 (void) { printf( "1\n" ); }
void func0 (void) { printf( "0\n" ); }
#define DEFUN(name) { #name, name }
typedef struct
{
const char *name;
void (*func)(void);
} funcptrs;
void call(funcptrs *ptrs, const char *name)
{
int i;
for(i = 0; ptrs[i].name; i++) {
if(strcmp(ptrs[i].name, name) == 0) {
ptrs[i].func();
break;
}
}
}
int main(int argc, char *argv[])
{
funcptrs funcs[] = {DEFUN(func0), DEFUN(func1), {NULL,NULL}};
call(funcs, "func0");
return 0;
}
答案 2 :(得分:0)
您可以使用枚举来表示数组的索引,并为它们指定有意义的名称。
#include <stdio.h>
#include <stdlib.h>
typedef void (*Handler)(void); /* A pointer to a handler function */
/* The functions */
void func3 (void) { printf( "3\n" ); }
void func2 (void) { printf( "2\n" ); }
void func1 (void) { printf( "1\n" ); }
void func0 (void) { printf( "0\n" ); }
enum{
FUNC0,
FUNC1,
FUNC2,
FUNC3
};
Handler jump_table[4] = {func0, func1, func2, func3};
int main (int argc, char **argv) {
/* Call appropriate function (func0 thru func3) */
jump_table[FUNC0]();
jump_table[FUNC1]();
jump_table[FUNC2]();
jump_table[FUNC3]();
return 0;
}
这将输出
0
1
2
3