假设我想用普通的 C 实现一个数值积分例程。它看起来像这样:

double integrate(double (*f)(double), double lower, double upper, double step));

我经常发现实际上依赖于多个变量的函数,我想整合第一个。说我想整合这个:
double func(double x, double z);

关于 x 。我无法将 func 传递给 integrate,因为它的签名错误。现在我知道了以下变通方法,这些变通方法是我们在学习数字类(class)时采用的:
  • 使用 C++

    我刚刚使用 C++ 和 ist std::bind 创建了一个可以传递给集成例程的仿函数(函数对象)。现在我只想使用 lambda 函数来完成它。
  • 对函数 中的函数使用 GCC 扩展

    使用 GCC,您可以在函数中声明一个函数。所以可以做
    // z is set to some value in this function scope here.
    double inner(double x) {
        return func(x, z);
    }
    

    并将该 inner 传递给 integrate 函数。这是不标准的,感觉不太好。
  • 使用全局变量
    z 的值可以存储在一个全局变量中。这将需要函数 func 是可编辑的,以使用全局变量中的 z 而不是参数。那可能是不可能的。然后它也会破坏并发性并且总体上很糟糕。

  • 在不破坏某些东西的情况下,是否存在与纯 C 相关的方法?

    最佳答案

    此问题的一种常见解决方案是将设计更改为:

    double integrate(double (*f)(double, void*), void*,
                          double lower, double upper, double step);
    

    在这里,您将额外的 void * 传递给 integrate ,然后将其传递回 f 。这可用于传递任意数据,在您的情况下,您将传递一个指向 z 的指针,并且在函数 f 中,您将指针转换回其原始类型并恢复值 z 。这种模式在 C 库中无处不在,例如这里是 pthread_create 的原型(prototype):
    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);
    

    关于使用 ISO C99 进行柯里化/绑定(bind),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23849343/

    10-11 21:59
    查看更多