# Using function pointers when argument list of the functions aren't known beforehand

This is a discussion on Using function pointers when argument list of the functions aren't known beforehand within the C Programming forums, part of the General Programming Boards category; Hi everyone, I am trying to write a generalized function to numerically solve a set of n simultaneous equations in ...

1. ## Using function pointers when argument list of the functions aren't known beforehand

Hi everyone,

I am trying to write a generalized function to numerically solve a set of n simultaneous equations in n unknowns, for any integer n. I'd like to pass the individual equations as function pointers to a variable length argument list, like this

Code:
`void solve_simul( int n, ... ) {/*stuff*/}`
The next n arguments will be pointers to the variables, and the next n after that will be pointers to the functions. I'm planning to have va_arg stick them in an array of function pointers inside solve_simul. If n was 3, the function call would be equivalent to

Code:
`solve_simul( 3, &x, &y, &z, phi0, phi1, phi2 );`
where each of the phi functions (in the case where n=3) would be like this:

Code:
`double phi0( double x, double y, double z ) {/*stuff*/}`
My problem is how to declare the function pointers inside the solve_simul function. It doesn't know beforehand how many variables the phi functions take, so how can I specify what type they are?

2. This is a guess - Give it a go: And if it works, it works; if it doesn't, it doesn't.

Try and make a typedef for a function pointer

Code:
`typedef (*f_pointer)(double x, double y, double z);`
And then assign the va_arg(argptr, f_pointer) to a local function pointer and handle them individually

3. Yes, but this will only work in the case of three equations in three unknowns. Let's say the next person comes along and wants to solve a system of five. The it would have to be

Code:
`typdef (*f_pointer)(double v, double w, double x, double y, double z);`
and there's no way of knowing how many equations and unknowns beforehand.

4. Think about it. How are you going to call your phi0 function from within solve_simul? You can't unpack the variable args into an argument list. However, you could probably pass the va_list itself.

But still, why don't you just use arrays?

5. Originally Posted by TheBigH
Yes, but this will only work in the case of three equations in three unknowns. Let's say the next person comes along and wants to solve a system of five. The it would have to be

Code:
`typdef (*f_pointer)(double v, double w, double x, double y, double z);`
and there's no way of knowing how many equations and unknowns beforehand.
What's wrong with using the va_arg system in the function pointer? Just make sure that your functions that you enter are handling the inputs in a "va_arg" way

Code:
`typedef (*f_pointer)(int n_of_inputs, ...)`

6. Originally Posted by oogabooga
Think about it. How are you going to call your phi0 function from within solve_simul? You can't unpack the variable args into an argument list.
I'm not sure I understand. I should be able to call phi0 from within solve_simul if I have a pointer to it, and pointers to all the variables it needs. And I do have all those things, but I don't know the length of phi0's argument list before I call solve_simul.

But still, why don't you just use arrays?
You mean, something like this:
Code:
`void solve_simul( int n, double **variables, double (*phis( int, double * ))[] ) {/*something like this?*/}`
Well, I've probably got the declaration slightly wrong but the point is to pass an array of pointers to functions that take arrays of their dependent variables. Yeah, that might work. Cheers.
This stuff makes my brain hurt.

7. Originally Posted by Click_here
What's wrong with using the va_arg system in the function pointer? Just make sure that your functions that you enter are handling the inputs in a "va_arg" way

Code:
`typedef (*f_pointer)(int n_of_inputs, ...)`
That's a good suggestion, IMO, but the syntax is wrong. You will have to call va_start in the solve_simul function, copy the va_list with va_copy for each function call, pass the copy to the function, and then call va_end on the copy each time.
Code:
`typedef (*f_pointer)(int, va_list *);`
(I haven't used stdarg for quite some time so this might not be 100% correct.)

8. Originally Posted by TheBigH
I'm not sure I understand. I should be able to call phi0 from within solve_simul if I have a pointer to it, and pointers to all the variables it needs. And I do have all those things, but I don't know the length of phi0's argument list before I call solve_simul.
You haven't thought it all the way through. Try actually writing code to do that and you'll see the problem.

This is clearly a job for arrays, not variable argument lists. It's just too ugly with varargs:
Code:
```#include <stdio.h>
#include <stdarg.h>

typedef void (*PFUNC)(int n, va_list *va);

void solve_simul(int n, ...) {
int i;
va_list va1, va2;
va_start(va1, n);
for (i = 0; i < n; i++)   // step va1 past doubles
va_arg(va1, double);
for (i = 0; i < n; i++) {
va_start(va2, n);
va_arg(va1, PFUNC)(n, &va2);
va_end(va2);
}
va_end(va1);
}

void f1(int n, va_list *va) {
int i;
printf("f1\n");
for (i = 0; i < n; i++)
printf("%f\n", va_arg(*va, double));
}

void f2(int n, va_list *va) {
int i;
printf("f2\n");
for (i = 0; i < n; i++)
printf("%f\n", va_arg(*va, double));
}

int main() {
solve_simul(2, 1.0, 2.0, f1, f2);
return 0;
}```
As for using arrays, the declaration of solve_simul would be something like:
Code:
`void solve_simul(int n, double *vars, double (*phis)(int , double *));`

9. Okay, so I'm persuaded to not use variable argument lists.

But shouldn't the declaration be
Code:
`void solve_simul(int n, double *vars, double *(*phis)(int , double *));`
since I will need an array of function pointers? Thanks for your help.

10. Array of pointers to functions - This might work
Code:
```Declare f_array as an array of pointers to a function (inputs integer, and pointer to double) returning a double
double (*f_array[])(int, double *)```

11. Yep, you're right. Those array square brackets need to be inside the round ones. Thanks.

12. Originally Posted by TheBigH
Okay, so I'm persuaded to not use variable argument lists. But shouldn't the declaration be ...
Yep, I didn't do that right. It's always better to use typedefs to simplify these things.
Code:
```#include <stdio.h>

typedef double (*PFUNC)(int, double*);

double f1(int n, double *vars) {
int i;
printf("f1\n");
for (i = 0; i < n; i++)
printf("%f\n", vars[i]);
return 0;
}

double f2(int n, double *vars) {
int i;
printf("f2\n");
for (i = 0; i < n; i++)
printf("%f\n", vars[i]);
return 0;
}

void solve_simul(int n, double *vars, PFUNC *phis) {
int i;
for (i = 0; i < n; i++)
(phis[i])(n, vars);
}

int main() {
double vars[2] = {1.0, 2.0};
PFUNC phis[2] = {f1, f2};
solve_simul(2, vars, phis);
return 0;
}```