假设我想用纯 C 语言实现一个数值积分例程。看起来像这样:
double integrate(double (*f)(double), double lower, double upper, double step));
Run Code Online (Sandbox Code Playgroud)
我经常发现函数实际上依赖于多个变量,并且我想对第一个变量进行积分。假设我想整合这个:
double func(double x, double z);
Run Code Online (Sandbox Code Playgroud)
关于x。我无法传递func给,integrate因为它的签名错误。现在我知道了以下解决方法,这些方法是我们在学习数字课程时使用的:
使用C++
我刚刚使用 C++ 和 iststd::bind创建了一个函子(函数对象),我可以将其传递给集成例程。现在我只需使用 lambda 函数来完成它。
在函数中使用 GCC 扩展函数
使用 GCC,您可以在函数中声明函数。所以一个人可以做
// z is set to some value in this function scope here.
double inner(double x) {
return func(x, z);
}
Run Code Online (Sandbox Code Playgroud)
并将其传递inner给integrate函数。这是不标准的,而且感觉不太好。
使用全局变量
的值z可以存储在全局变量中。这将要求该函数可编辑以从全局变量而不是参数中func使用。z那可能是不可能的。然后它也会破坏并发性并且总体来说很糟糕。
是否存在一种方法可以在不破坏某些内容的情况下使用普通 C 进行处理?
该问题的一种常见解决方案是将设计更改为:
double integrate(double (*f)(double, void*), void*,
double lower, double upper, double step);
Run Code Online (Sandbox Code Playgroud)
在这里,您传递了一个附加的void *to integrate,并且该附加值被传递回f。这可用于传递任意数据,在您的情况下,您将传递一个指向 的指针z,并在函数内f将指针强制转换回其原始类型并恢复值z。这种模式在 C 库中普遍存在,例如这里是pthread_create的原型:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Run Code Online (Sandbox Code Playgroud)