2012-03-29 63 views
4

請給我一些跳轉表的使用示例。我看到的維基百科這個例子:跳轉表示例C

#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()

+1

「使用索引是否有一種方法可以使用函數本身的名稱」您要查找的是更高級別的語言還是哈希表。散列表將是字符串 - >函數指針。 – Corbin 2012-03-29 19:36:20

+3

如果你想用函數本身的名字來調用,那麼爲什麼你首先需要一個跳轉表? – 2012-03-29 19:37:15

+0

我沒有真正讀過你的最後一個例子,現在我剛剛做了,我相信@PavanManjunath有一點。你究竟想要做什麼?我假設你想要一個char *並根據它調用一個函數。就像在PHP中你可以做$ func =「strtolower」; echo $ func('CORBIN');. – Corbin 2012-03-29 19:39:57

回答

5

當然,但你需要將它們聲明爲函數指針並首先初始化它們。儘管如果必須說明函數名稱,這會破壞跳轉表的目的。

例如

#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; 
} 
+0

好吧,它*可能有意義:如果你有不同的結構實例,例如實現一種虛函數表。 – Matthias 2012-03-29 19:46:56

+0

這是醜陋的。改爲用塊代替。 – 2012-03-29 19:53:44

7

您當然可以創建一個包含指向函數的指針的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... 
}; 

然後一些更高級別的功能可以接收其中的一個,並打開/關閉/讀/寫某些設備,而不必知道涉及設備的確切身份。當然,對於一個真正的操作系統來說,它比這個要複雜一些,但總體思路是(或者至少可以)非常相似。

+0

+1 - 這與我認爲OP所要求的非常接近。這是80年代當我們在C++虛擬功能之後感到興奮時的一種正常技術,但在PC上只有C。 – gbulmer 2012-03-29 20:12:38