0

我需要在原始 ANSI C (1989) 中解决一个问题。

我有一些指针(void *func)可以使用(int n)双参数起作用,并且有double values[]带有n数字的数组。所以我想用n值中的参数运行我的函数。

例如,我有功能:

double hypotenuse(double x, double y, double z);

所以

void *func = (void *)hypotenuse; double values[3] = {5, 4, 3}; int n = 3;

我想做这样的事情:

func(n, values);

问题是我不能改变函数的原型,所以我需要以某种方式做到这一点(也许是一些宏?)。

4

2 回答 2

4

主要问题是您必须根据参数的数量(即取决于n变量)以不同的方式转换指针。

一种方法是使用包含switch参数号语句的包装函数:

double wrapper(void *func, double args[], int n)
{
    switch (n)
    {
    case 0:
        return ((double (*)(void)) func)();
    case 1:
        return ((double (*)(double)) func)(args[0]);
    case 2:
        return ((double (*)(double, double)) func)(args[0], args[1]);
    case 3:
        return ((double (*)(double, double, double)) func)(args[0], args[1], args[2]);
    default:
        printf("Error: wrapper called with %d arguments\n", n)
        break;
    }

    return 0.0;
}
于 2013-02-15T08:09:36.900 回答
2

昨晚写的很晚——但是当我试图发布它时,我的互联网连接中断了。我看到约阿希姆写了基本相同的答案。


在限制范围内,这将起作用:

#include <assert.h>

extern double function_invoker(void *func, int n, double *values);

double function_invoker(void *func, int n, double *values)
{
    switch (n)
    {
    case 0:
        return (*(double (*)(void))func)();
    case 1:
        return (*(double (*)(double))func)(values[0]);
    case 2:
        return (*(double (*)(double, double))func)(values[0], values[1]);
    case 3:
        return (*(double (*)(double, double, double))func)(values[0], values[1], values[2]);
    default:
        assert("Need more entries in the switch in function_invoker()" == 0);
        return(0.0);
    }
}

明显的限制是您要在switch. 我见过松散相似的代码多达 100 多个参数。我不确定为什么认为这是必要的。

该代码在 Mac OS X 10.8.2 上的 GCC 4.6.0 下编译时没有警告:

$ gcc -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
    -Wold-style-definition -c x.c
$

但是如果你用double (*)()代替void *,你会得到:

$ gcc -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
    -Wold-style-definition -c x.c
x.c:3:1: warning: function declaration isn’t a prototype [-Wstrict-prototypes]
x.c:5:1: warning: function declaration isn’t a prototype [-Wstrict-prototypes]
$
于 2013-02-15T15:52:51.970 回答