Sorry about replying to myself but I must make a correction.
Ben Bacarisse said:
As the other Ben said,nothing special here. If you don't know how to
use va_arg and friends for "ordinary" argument types, post a simpler
example first. You can then move to function pointers with no change.
That's not quote true. There is something special here. The type must
be compatible with (take that to mean "the same as" for now) the type of
the supplied argument, but it must be in a form that enable a pointer
type to be derived form it by simply appending a *. See below for
details.
This looks odd. fp1 is unused and the ... seems to refer to list of
function pointers of the same type as fp1. If there must always be one
function pointer (hence your declaration of one) then you should use it
in the example code. If there can be zero or more function pointers,
then you should stop at "double x, ...".
You always put the last declared parameter here: fp1 in this case.
You must put the type of the argument that the caller will pass here.
Presumably double (*)(double, int). This rule can be relaxed a little
bit, but I see no reason to make use of that permission here.
The trouble is that a pointer to a pointer of that type is written
double (**)(double, int) so my answer fails to meet the extra
requirement in 7.16.1.1 p2. It worked when I tried which is what
stopped me from checking. I think you need a typedef here to make it
conform:
typedef double (*func_ptr)(double, int);
...
func_ptr fp_new = var_arg(vl, func_ptr);
*fp_new is an expression of function type. You can't test it like this.
You can call the function *fp_new or you can test if fp_new == NULL.
Since I'm here, note that, technically, passing NULL in a call to myFunc
is not correct. It's type, after promotion, is not compatible with the
type you intend to give to va_arg. This you must end the argument list
with (func_ptr)NULL (or (double (*)(double, int))NULL if the typedef is
not visible here).
As it happens, the same problem occurs with ordinary pointers when
passing them to vararg functions. NULL could simply be 0, and 0
promotes to the integer 0 when being passed to a vararg function in the
.... position. To pass a null pointer you need to write (void *)0.
You can test for NULL in your function, but you can never rely on
passing NULL as a null pointer to a vararg function.