2011-10-06 34 views
11

這個問題幾乎說明了一切。C:如何使用單個函數指針數組來計算具有可變參數計數的函數?

我不知道如何做到這一點,並沒有任何地方靠近任何工作。

這裏的一些功能。例如:

add(int x, int y) { 
    return x+y; 
} 

,並

mean(int x1, int y1, int x2, int y2) { 
    return (x1 + y1 + x2 + y2)/4; 
} 

到目前爲止,我已經使用的typedef既試過,但我想不出如何使一些點之一任一種類型:

typedef int (*mathfunc2)(int x, int y); 
typedef int (*mathfunc4)(int x1, int y1, int x2, int y2); 

????? func_table[2] = {add, mean}; 

回答

25

您需要選擇一個函數指針類型作爲「通用函數指針」 ,使用該類型來定義您的數組,並使用顯式強制轉換。將一個函數指針類型轉換爲另一個函數指針類型然後再返回將保證該值。

換句話說:

typedef int (*generic_fp)(void); 

generic_fp func_table[2] = { (generic_fp)add, (generic_fp)mean }; 

然後打電話給add,你需要將它轉換回正確的類型:

result = ((mathfunc2)func_table[0])(x, y); 

,如果你發現它更可口,您可以定義一些宏:

#define FUNC_2(f, p1, p2) ((mathfunc2)(f))(p1, p2) 
#define FUNC_4(f, p1, p2, p3, p4) ((mathfunc4)(f))(p1, p2, p3, p4) 

result = FUNC_2(func_table[0], x, y); 
+0

這就是訣竅!謝謝你,先生。我希望能夠記住這一點,如果我獲得了15個聲望並給你一個向上箭頭:) – vaughanj

+0

由於參數的原因,我在印象函數指針的行爲與常規的空指針不同。你不能混合函數指針和不同的參數,因爲堆棧在清理時會損壞。我誤解了一些東西嗎? – Ioan

+0

@Ioan:您必須通過一個與聲明的函數類型兼容的指針來調用函數 - 這意味着如果您將函數指針轉換爲不同的類型進行存儲,則必須將其轉換回正確的類型以調用功能。這個答案中的例子是這樣做的。 – caf

0

這兩個函數類型是不兼容的。嚴格地說,它們可以使用完全不同的參數傳遞來實現。例如,一個實現可能會選擇所有具有最多3個參數的函數通過寄存器接收它們,而所有其他函數通過堆棧接收它們。

你可以做的是通過可變參數定義兩個函數,使它們遵循相同的參數傳遞方案。

無論如何,你打算如何調用這些函數,不知道他們期望有多少參數?

3

您可以使用Facade Pattern這樣的:

int add(int x, int y); 
int mean(int x1, int y1, int x2, int y2); 

typedef int (*operation_fp)(int argc, int* argv); 

int add_wrapper(int argc, int* argv) { return add(argv[0], argv[1]); } 
int mean_wrapper(int argc, int* argv) { return mean(argv[0], argv[1], argv[2], argv[3]); } 

operation_fp func_table[2] = { add_wrapper, mean_wrapper }; 

雖然代碼是醜陋的,它的工作。您應該在包裝中添加一些驗證邏輯。

1
int (*func[])() = { add, mean }; 
+0

類型爲int(*)(int,int)和int(*)(int,int,int,int)的函數指針與類型爲int(*)的函數指針不兼容(int, ...)'。 – caf

+0

確定,編輯爲() – BLUEPIXY