Home > Software design >  Creating function pointers in C with arguments
Creating function pointers in C with arguments

Time:08-31

So I need to write some code that performs partial integration. I have a numerical integrator schematically represented by

double integrate(double (*func)(double));

and suppose it works properly, i.e. for a function double f(double x), integrate(f) gives the right result. What I have instead, however, are functions that look like

double f(double x, double y);

and I want to perform integration on only the first variable - so dynamically generate pointers to functions like g(x)=f(x,1) or h(x)=f(x,2) and pass them to integrate. I guess prototypically what I want is to define a function within another,

double compute(double y){
  double g(double x){
    return f(x, y);
  }
  return integrate(g);
}

which I know is not part of ANSI C even though GCC allows it (maybe I shouldn't care and just use it then). So, what would be the standard, C18 approved way to get this behavior? If the only possibility is to copy over the code of integrate to the inside of compute, I guess I'll just use the GCC extension even though my LSP constantly complains about it, but I'm interested in what the "proper" program would look like.

CodePudding user response:

Using the base C language, that is code that is strictly conforming as the standard defines it, here are three ways to do it.

Define a function that hard-codes the additional argument:

double g1(double x) { return f(x, 1); }
…
integrate(g1);

Define a function that gets the additional argument from an externally defined object:

double y;
double g(double x) { return f(x, y); }
…
y = 1;
integrate(g);

Modify integrate to take a pointer to additional information and use that to pass information to the function being integrated:

double integrate(double (*func)(double, const void *))

struct MyData { double y; }; // This structure can contain whatever you want.

double g(double x, const void *p)
{
    const void struct MyData *data = p;
    return f(x, data->y);
}
…
struct MyData data = { 1 };
integrate(g, &data);

With GCC, you can use one of its extensions beyond the C standard that allows you to define functions within functions:

double compute(double y)
{
    double g(double x) { return f(x, y); }
    return integrate(g);
}

That can also be done in Clang using the blocks extension, but that would also require modifying integrate to accept a block.

  • Related