![](/img/trans.png)
[英]Is it possible to call a function using a function pointer with number and type of arguments known only at runtime
[英]How do I call a function pointer where number of arguments if only known at runtime
在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;
}
上面的程序起作用,並輸出:131 27 9 0這是預期的輸出。 問題是,我需要在switch語句中為每個要支持的參數數目添加一個大小寫。 所以我的問題是:有沒有一種更簡單的方法來做到這一點,而且它並不那么丑陋,並且可以處理任意數量的參數?
如果可能的話,代替編寫用於每個參數數量的單獨函數,而是編寫一個使用int
數組代替計數的函數,甚至考慮使用<stdarg.h>
但您仍然需要某種哨兵或計數。
否則,您將陷入語言標准本身無法保證的非便攜式實現特定行為。
使用某些調用約定(例如, 在此處閱讀x86示例) ,可以使用附加參數來調用該函數,而在正確使用相關的參數時,它們將在寄存器或堆棧中被忽略,然后由於原始堆棧指針被丟棄而被丟棄。在其他體系結構上,函數返回時調整堆棧指針的數量與函數參數的數量有關,因此上述方法將崩潰:如果您想閱讀編譯器/系統的約定並且有一個非-便攜式解決方案,這是一個選擇。
否則,再次取決於您的調用約定,您可能能夠在調用函數之前使用匯編語言在堆棧上推送一些參數。 我已經在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);
如果您使用錯誤的數量或類型的參數調用函數,則會導致未定義的行為,但是,只要像您在代碼中實際那樣跟蹤參數的數量,就可以很好地定義它。
沒有比這更簡單的方法來保留可移植性和功能。 在某些系統上,您會通過傳遞額外的偽參數來避免麻煩。
當然,您可以重寫函數,以采用包含TonyD建議的可變長度參數列表的結構。 您還可以為每個帶有固定參數列表的函數編寫thunk,但這將與switch表一樣多。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.