INFO: Extracting Function ptr from a Variable arg List Function

Last reviewed: September 2, 1997
Article ID: Q47961

The information in this article applies to:
  • Microsoft C for MS-DOS, versions 5.1, 6.0, 6.0a, 6.0ax
  • Microsoft C/C++ for MS-DOS, version 7.0
  • Microsoft Visual C++ for Windows, versions 1.0, 1.5
  • Microsoft Visual C++ 32-bit Edition, versions 1.0, 2.0, 2.1, 4.0, 5.0

SUMMARY

In Microsoft C the va_arg() macro may be used 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
   */
   }
Keywords          : CLngIss kbcode kbfasttip
Version           : MS-DOS:6.0,6.00a,6.00ax,7.0; WINDOWS:1.0,1.5,1.51,1.52;  WINDOWS NT:1.0,2.0,2.1,4.0,5.0
Platform          : MS-DOS NT WINDOWS
Issue type        : kbinfo


================================================================================


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: September 2, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.