繁体   English   中英

如果仅在运行时知道参数数目,如何调用函数指针

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM