2014-09-29 52 views
0

在c中,請考慮這種情況。我有一個函數指針數組,我想調用它們中的每一個。我也有一個整數數組,告訴我每個參數需要多少個參數。我第三次有一組我想要調用它們的參數。下面的程序是使用此一程序的一個例子:如何在調用運行時知道參數數量的情況下如何調用函數指針

int foo(int a, int b, int c){ 
    return a+b+c; 
} 

int bar(int a, int b){ 
    return a+b; 
} 

int baz(int a){ 
    return a; 
} 

int qux(){ 
    return 0; 
} 


int main(){ 
    void *funcArray[4] = {foo, bar, baz, qux}; //an array of function pointers, all of which return ints but have different numbers of arguments 
    int argArray[3+2+1+0] = {100,30,1, 20,7, 9}; //these are the arguments to the functions to be executed 
    int numArgsArray[4] = {3,2,1,0}; //these are the numbers of arguments that each function takes in the funcArray array 
    int nextArg = 0; //used to keep track of which argument goes to which function 

    for (int i = 0; i<4; i++){ 
     int result; 
     switch(numArgsArray[i]){ 
     case 0://if the function takes no args, just call it 
      result = ((int(*)())funcArray[i])(); 
      break; 
     case 1://if the function takes one arg, pass it the argument when calling it 
      result = ((int(*)(int))funcArray[i])(argArray[nextArg]); 
      nextArg += 1; 
      break; 
     case 2://if the function takes two arguments, pass it both when calling 
      result = ((int(*)(int, int))funcArray[i])(argArray[nextArg], argArray[nextArg+1]); 
      nextArg += 2; 
      break; 
     case 3://if the function takes three args, pass it all three when calling 
      result = ((int(*)(int, int, int))funcArray[i])(argArray[nextArg], argArray[nextArg+1], argArray[nextArg+2]); 
      nextArg += 3; 
      break; 
     } 
     printf("%d\n", result); 
    } 

    return 0; 
} 

上述程序工作,並將其輸出:這是intented輸出。問題是我需要在switch語句中爲每個我想支持的參數個數設置一個大小寫。 所以我的問題是:有沒有一個更簡單的方法來做到這一點,這不是很難看,並將與任何數量的參數一起工作?

+3

注意:在標準C中不允許從'pointer to function'到'void *'的轉換。 – BLUEPIXY 2014-09-29 01:54:32

+0

實現一個輕量級向量並將指針傳給它。 – 2014-09-29 01:54:56

+1

只需將argc和argv傳遞給函數即可。 – chux 2014-09-29 01:57:32

回答

3

如果可能的話,而不是爲參數的每個號碼不同的功能,編寫一個函數,它的int秒的陣列,而不是數量,甚至可以考慮使用<stdarg.h>但你仍然需要某種定點或計數。

否則,你將不會被語言標準本身保證非便攜執行指定的行爲....

對於某些調用約定(如read here for x86 examples,你可以調用額外的參數和它們的功能當正確使用感興趣的內容時,它將在寄存器或堆棧中被忽略,然後在原始堆棧指針被恢復時被丟棄。在其他體系結構中,函數返回時調整堆棧指針的數量與因此上述方法會崩潰如果您想了解您的編譯器/系統的慣例並且有一個非便攜式解決方案,那麼這是一個選項。

否則,再次根據您的調用約定,您可以在調用函數之前使用匯編語言在堆棧上推送一些參數。我已經看到了代碼在stackoverflow上執行的問題,但可能需要一些挖掘才能找到。不過,你需要一個與你正在使用的調用約定相對應的。如果你調用一個函數參數的錯號碼或類型,然後它會導致不確定的行爲,但只要你保持跟蹤你的論點的具體計算像你

typedef int (*FuncP)(); // function returning int and taking unspecified arguments 
FuncP func_array[4] = { foo, bar, baz, qux }; 

// ... 

// cast unnecessary 
case 1: 
    result = funcArray[i](arg1); 

+0

我的目標實際上並不是有添加不同數量的整數的函數,這只是例如。實際上,這些功能可以分別做一些完全不同的事情。 – while1fork 2014-09-29 02:03:36

+0

@ while1fork:好,「完全不同的東西」是開放式的,我不知道還有什麼進一步的建議...... ;-) – 2014-09-29 02:06:16

2

這可以稍微改善實際上在你的代碼中,然後它是明確的。

有沒有簡單的方法保留便攜性,並保留它們的功能。在某些系統上,您會通過傳遞額外的虛擬參數而逃脫。

當然,你可以重寫函數來獲取一個包含可變長度參數列表的結構,如TonyD所示。你也可以爲每個採用固定參數列表的函數編寫thunks,但是這與開關表一樣有效。

相關問題