In file1.h
// find the root of a function of one variable
double rootfind(double (*fp)(double), double start, double end);
In file2.h
// a function of multiple variables
double myfun(double a, double b);
double test();
In file2.c
double myfun(double a, double b)
{
return (a+3.0)*(a-1.0)*(a-1.0)*b;
}
double test()
{
double b, start, end;
start = -4.0;
end = 4.0/3.0;
b = 2.0;
// How do I use the rootfinding function to find the root of myfun
// where b is set as a constant in this function?
// How do i find the root of myfun(x,2.0)?
}
I want to keep the rootfind function generic and not pass extra parameters in. I also don't want to use the gcc extension for nested functions.
You are asking about something known as closures which are not supported in standard C90/C99. If you do plan on doing this, you either have to:
std::bind
function. Most of those probably seem confusing/intimidating, that's because there's really no good way to do what you want in C. This is mostly because it's very dangerous (major security hole) to have functions rewritten at run time in C.
An example of a top level static function (place this just above your main
function):
static myfun_single_b = 2.0;
static double myfun_single(double a) {
return myfun(a, myfun_single_b);
}
The reason we use the static
keyword here is so that the name of the variable and the name of the function won't conflict with other function/variable names from other source files.
You can write a wrapper function:
static double wrapper(double a) {
return myfun(a, 3.0);
}
and use rootfind()
on that. You could make it more general (ie to support different values of the second argument to myfun()
) by making it take the value of myfun()
's second argument from a file-scope variable:
static double b;
static double wrapper(double a) {
return myfun(a, b);
}
You could even generalize it more by making the wrapper call a two-arg function via a file-scope function pointer:
static double b;
static double (*wrapped)(double, double);
static double wrapper(double a) {
return (*wrapped)(a, b);
}
That's about the limit of the indirection you can perform, but it affords a fair amount of latitude.
If you can modify rootfind
, the proper way to fix it would be to add a context parameter to the function pointer, like
double rootfind(double (*fp)(double, void *), double start, double end, void *context);
You can then create a context struct containing your second argument b
and pass a pointer to it via the context argument.
This way, both global state and run-time code generation are avoided. The rootfind
function also remains generic.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.