Everybody else has given you the canonical answer "Nested functions are not allowed in standard C" (so any use of them depends on your compiler).
Your revised example is:
double stuff(double a, double b)
{
struct parameters
{
double a, b;
};
double f(double x, void * params)
{
struct parameters p = (struct parameters *) params;
double a = p->a, b = b->b;
return some_expression_involving(a,b,x);
}
struct parameters par = {a,b};
return integrate(&f, &par); // return added!
}
Since you say that the functions such as the integrator need
double (*f)(double x, void * par);
I don't see why you really need nested functions at all. I would expect to write:
struct parameters
{
double a, b;
};
static double f(double x, void *params)
{
struct parameters p = (struct parameters *) params;
double a = p->a, b = b->b;
return some_expression_involving(a,b,x);
}
double stuff(double a, double b)
{
struct parameters par = { a, b };
return integrate(f, &par);
}
The code above should work in C89 (unless there's an issue with initializing 'par' like that) or C99; this version of the code is for C99 only, using a compound literal for the parameter (section 6.5.2.5 Compound literals):
double stuff(double a, double b)
{
return integrate(f, &(struct parameters){a, b});
}
The chances are excellent that you have only a few variations on the 'struct parameters' type. You do need to provide separate (sufficiently) meaningful names for the various functions - you can only have one function called 'f' per source file.
The only marginal, tiny benefit of the nested function version is that you can be sure that no other function than stuff calls f. But given the example code, that is not a major benefit; the static definition of f means that no function outside this file can call it unless passed a pointer to the function.