在C中指定函数参数

时间:2016-03-26 09:20:47

标签: c function

我想实现一个密度为R ^ n的概率空间,如下所示:

typedef struct _ProbabilitySpace {
  int dim;
  double (*density)(double *first, double *last);
  /** more stuff **/
} ProbabilitySpace;

现在,通过这种实现,如何实现一系列密度函数?可以说,我想实现高斯族,然后我可以写一个函数

double gaussian(struct vec mu, struct mat sigma, double *first, double *last){
  /** gaussian density function here */
}

如您所见,此密度不仅取决于参数* first和* last,还取决于mu和sigma。我想给用户一个指定mu和sigma的可能性(可能在运行时),而不必一直传递它。此外,此函数可能用于不同ProbabilitySpace对象中的(mu,sigma)的不同组合。

C ++中的解决方案是创建另一个类:

class _Density{
  public:
    double evaluate(double* first, double* last);
  private: 
    /** any private parameters **/
};

任何一组概率分布都可以从该类继承并定义私有参数,用户必须在构造函数中初始化这些参数。然后,评估成员函数可以访问这些私有参数。

但是在C中,我没有看到任何方法来为任何函数指定参数列表以外的参数,因为它们无法访问其他成员变量。

也许有人可以建议解决方案?

3 个答案:

答案 0 :(得分:2)

  

任何一组概率分布都可以从该类继承并定义私有参数,用户必须在构造函数中初始化这些参数。然后,评估成员函数可以访问这些私有参数

你知道,C ++每次都会将隐藏参数this传递给成员函数evaluate,这允许使用这些私有参数。在C中你必须自己做。

struct _Density{
  /** any private parameters **/
} d;

InitDensity(&d, ...); /* constructor */
gaussian(&d, first, last);
/* etc. */

实际上,C ++编译器会自动为您完成同样的工作。

答案 1 :(得分:0)

您的C ++解决方案也不起作用,因为指向成员函数_Density::evaluate的指针与double (*density)(double *first, double *last)函数指针类型不兼容。

这种不兼容的原因是非静态成员函数隐式地使用了额外的参数this。编译器隐藏了该参数的存在,但它存在。

C ++中的解决方案是使用std::function代替函数指针。但是,在C中不能做同样的事情,所以惯用解决方案是将类型void*的额外参数传递给系列中的所有函数,让它们在内部“破解”参数,提取无论他们需要什么:

typedef struct _ProbabilitySpace {
  int dim;
  double (*density)(double *first, double *last, void *user_data);
  /** more stuff **/
} ProbabilitySpace;

typedef struc {
    struct vec mu;
    struct mat sigma;
} GaussianData;

double gaussian(double *first, double *last, void *user_data){
    GaussianData *data = (GaussianData*)user_data;
    ...
}

这种方法统一了函数签名,允许将各种参数传递给指针调用的函数。您需要确保这些参数在函数指针可以访问它们时保持有效,例如,您没有存储指向即将超出范围的本地的指针。

答案 2 :(得分:0)

您可以通过以下方式执行此操作

typedef struct _ProbabilitySpace {
  int dim;
  double (*density)(double *first, double *last);
  /** more stuff **/
} ProbabilitySpace;

//...
double gaussian( double *first, double *last )
{
    //... 
    gaussian_impl( /*...*/ );
}

static double gaussian_impl(struct vec mu, struct mat sigma, double *first, double *last){
  /** gaussian density function here */
}

//...

ProbabilitySpace p;

p.density =  gaussian;