INF: Extracting Function ptr from a Variable arg List Function

ID Number: Q47961

5.10 6.00 6.00a 6.00ax 7.00 | 5.10 6.00 6.00a

MS-DOS | OS/2

Summary:

In Microsoft C versions 5.0, 5.1, 6.0, 6.0a, 6.0ax, and C/C++ version

7.0, use the va_arg() macro to remove an item from a variable argument

list. When the element to be removed is complex, however, you may have

to typedef the item type. This is necessary because the va_arg() macro

requires you to provide the type of the item to be removed from the

list. For a pointer to a function, if you were to put the item type

(the declaration of the function ptr) as follows

FuncPtr = va_arg (arg_list, (int(*)(void)) );

the compiler would yield the following error:

C2059: Syntax Error : ')'

You could try to get around this by grabbing the function pointer as a

data pointer, and then typecasting it to a function pointer, as in the

following line:

FuncPtr = (int (*)(void)) va_arg (arg_list, char *);

This will work; however, you will get the following warning:

C4074: Non-standard extension used, cast of data pointer

to function pointer

The best solution is to typedef the function pointer. With a typedef,

you avoid both the error and the warning.

More Information:

The following sample code passes a function pointer to a variable

argument list function, changes that pointer, and returns it to the

calling procedure. To implement this, however, you need to pass the

function pointer by reference. For this reason, a pointer is typedef'd

to a function pointer. Once in the variable argument list function,

the pointer is dereferenced to the function pointer to get at the

actual function pointer.

Sample Code

-----------

#include <stdio.h>

#include <stdarg.h>

typedef void (*FuncPtr)(void);

typedef FuncPtr *PFuncPtr;

void hello(void);

void varfunc(int, ...);

FuncPtr func1, func2;

int i;

void main(void) {

func1 = hello;

printf ("Function pointer: func1 now points to Hello()\n");

printf ("About to use func1 to make a call to Hello()\n\n");

func1();

printf ("Now lets pass these function pointers to our variable");

printf (" argument list\n");

varfunc(2, &func1, &func2); /* To alter ptr, pass by reference */

printf ("\nAfter the call to the variable argument procedure,\n");

printf ("function pointer: func2 now points to Hello()\n");

printf ("About to use func2 to make a call to Hello()\n\n");

func2();

}

void hello(void) {

printf ("Hello, I'm in the procedure HELLO()\n");

}

void varfunc(int i, ...) {

va_list arg_ptr;

PFuncPtr tmpfptr; /* Temporary ptr to function ptr */

printf ("\nIn function VARFUNC\n");

va_start (arg_ptr, i);

printf ("%d arguments were passed\n", i);

tmpfptr = va_arg (arg_ptr, PFuncPtr); /* Grab pointer to fnptr */

*tmpfptr = hello; /* Assign fnptr addr of fn */

tmpfptr = va_arg (arg_ptr, PFuncPtr); /* Grab pointer to fnptr */

*tmpfptr = hello; /* Assign fnptr addr of fn */

}

Additional reference words: 5.00 5.10 6.00 6.00a 6.00ax 7.00