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