va_arg(), va_copy(), va_end(), va_start() — Access function arguments

Standards

Standards / Extensions C or C++ Dependencies

ISO C
C99
Single UNIX Specification, Version 3

both  

Format

#include <stdarg.h>

var_type va_arg(va_list arg_ptr, var_type);
void va_end(va_list arg_ptr);
void va_start(va_list arg_ptr, variable_name);
C99:
#define _ISOC99_SOURCE
#include <stdarg.h>

var_type va_arg(va_list arg_ptr, var_type);
void va_end(va_list arg_ptr);
void va_start(va_list arg_ptr, variable_name);
void va_copy(va_list dest, va_list src);

General description

The va_arg(), va_end(), and va_start() macros access the arguments to a function when it takes a fixed number of required arguments and a variable number of optional arguments. You declare required arguments as ordinary parameters to the function and access the arguments through the parameter names.

The va_start() macro initializes the arg_ptr pointer for subsequent calls to va_arg() and va_end().

The argument variable_name is the identifier of the rightmost named parameter in the parameter list (preceding , …). Use the va_start() macro before the va_arg() macro. Corresponding va_start() and va_end() macro calls must be in the same function. If variable_name is declared as a register, with a function or an array type, or with a type that is not compatible with the type that results after application of the default argument promotions, then the behavior is undefined.

The va_arg() macro retrieves a value of the given var_type from the location given by arg_ptr and increases arg_ptr to point to the next argument in the list. The va_arg() macro can retrieve arguments from the list any number of times within the function.

The macros also provide fixed-point decimal support under z/OS® XL C. The sizeof(xx) operator is used to determine the size and type casting that is used to generate the values. Therefore, a call, such as, x = va_arg(ap, _Decimal(5,2)); is valid. The size of a fixed-point decimal number, however, cannot be made a variable. Therefore, a call, such as, z = va_arg(ap, _Decimal(x,y)) where x = 5 and y = 2 is invalid.

The va_end() macro is needed by some systems to indicate the end of parameter scanning.

va_start() and va_arg() do not work with parameter lists of functions whose linkages were changed with the #pragma linkage directive.

stdarg.h and varargs.h are mutually exclusive. Whichever #include comes first, determines the form of macro that is visible.

The type definition for the va_list type is normally "char *va_list[2]". Some applications (especially ported applications) require that the va_list type be defined as "char *va_list". This alternate va_list type is available if the user defines the feature test macro _VARARG_EXT_ before the inclusion of any system header file. If the _VARARG_EXT_ feature test macro is defined, va_list will be typed as char * va_list, and the functions vprintf(), vfprintf(), vsprintf(), and vswprintf() will use this alternate va_list type.

The va_copy() function creates a copy (dest) of a variable of type va_list (src). The copy appear as if it has gone through a va_start() and the exact set of sequences of va_arg() as that of src.

After va_copy() initializes dest, the va_copy() macro shall not be invoked to reinitialize dest without an intervening invocation of the va_end() macro for the same dest.

Returned value

The va_arg() macro returns the current argument.

The va_end(), va_copy(), and va_start() macros return no values.

Example

CELEBV01
⁄* CELEBV01                                      

   This example passes a variable number of arguments to a function,            
   stores each argument in an array, and prints each argument.                  

 *⁄                                                                             
#include <stdio.h>                                                              
#include <stdarg.h>                                                             
                                                                                
void vout(int max, ...);                                                        
                                                                                
int main(void)                                                                  
{                                                                               
   vout(3, "Sat", "Sun", "Mon");                                                
   printf("\n");                                                                
   vout(5, "Mon", "Tues", "Wed", "Thurs", "Fri");                               
}                                                                               
                                                                                
void vout(int max, ...)                                                         
{                                                                               
   va_list arg_ptr;                                                             
   int args = 0;                                                                
   char *days[7];                                                               
                                                                                
   va_start(arg_ptr, max);                                                      
   while(args < max)                                                            
   {                                                                            
      days[args] = va_arg(arg_ptr, char *);                                     
      printf("Day:  %s  \n", days[args++]);                                     
      }                                                                         
   va_end(arg_ptr);                                                             
}                                                                               
                                                                                
Output
Day:  Sat
Day:  Sun
Day:  Mon

Day:  Mon
Day:  Tues
Day:  Wed
Day:  Thurs
Day:  Fri
/* This example uses a variable number of arguments for
   fixed-point decimal data types.
   The example works in z/OS XL C only.
 */
#include <stdio.h>
#include <stdarg.h>
#include <decimal.h>

void vprnt(int, ...);

int main(void) {
  int i = 168;
  decimal(10,2) pd01 = 12345678.12d;
  decimal(20,5) pd02 = -987.65d;
  decimal(31,20) pd03 = 12345678901.12345678900987654321d;
  int j = 135;

  vprnt(0, i, pd01, pd02, pd03, j);

  return(0);
}

void vprnt(int whichcase, ...) {
  va_list arg_ptr;
  int m, n;
  decimal(10,2) va01;
  decimal(20,5) va02;
  decimal(31,20) va03;

  va_start(arg_ptr, whichcase);

  switch (whichcase) {
    case 0:
      m = va_arg(arg_ptr, int);
      va01 = va_arg(arg_ptr, decimal(10,2));
      va02 = va_arg(arg_ptr, decimal(20,5));
      va03 = va_arg(arg_ptr, decimal(31,20));
      n = va_arg(arg_ptr, int);
      printf("m    = %d\n", m);
      printf("va01 = %D(10,2)\n", va01);
      printf("va02 = %D(20,5)\n", va02);
      printf("va03 = %D(31,20)\n", va03);
      printf("n    = %d\n", n);
      break;
    default:
      printf("Illegal case number : %d\n", whichcase);
  }

  va_end(arg_ptr);
}
Output:
m    = 168
va01 = 12345678.12
va02 = -987.65000
va03 = 12345678901.12345678900987654321
n    = 135
CELEBV02
⁄* CELEBV02

   These examples use the _XOPEN_SOURCE feature test macro,
   This ecample passes a variable number of arguments to a function,
   stores each argument in an array, and prints each argument.

 *⁄
#define _XOPEN_SOURCE
#include <stdio.h>
#include <varargs.h>

void vout(va_alist)
va_dcl
{
   va_list arg_ptr;
   int args = 0;
   int max;
   char *days[7];

   va_start(arg_ptr);
   max = va_arg(arg_ptr, int);
   while(args < max) {
        days[args] = va_arg(arg_ptr, char *);
        printf("Days:       %s  \n", days[args++]);
        }
   va_end(arg_ptr);
}

int main(void)
{
    vout(3,"Sat","Sun","Mon");
    printf("\n");
    vout(5,"Mon","Tues","Wed","Thurs","Fri");
}
/* This example uses a variable number of arguments for
   fixed-point decimal data types.
   The example works in z/OS XL C only.
 */
#define  _XOPEN_SOURCE
#include <stdio.h>
#include <varargs.h>
#include <decimal.h>


void vprnt(va_alist)
va_dcl
{
  va_list arg_ptr;
  int m, n, whichcase;
  decimal(10,2) va01;
  decimal(20,5) va02;
  decimal(31,20) va03;

  va_start(arg_ptr);
  whichcase = va_arg(arg_ptr, int);

  switch (whichcase) {
    case 0:
      m = va_arg(arg_ptr, int);
      va01 = va_arg(arg_ptr, decimal(10,2));
      va02 = va_arg(arg_ptr, decimal(20,5));
      va03 = va_arg(arg_ptr, decimal(31,20));
      n = va_arg(arg_ptr, int);
      printf("m    = %d\n", m);
      printf("va01 = %D(10,2)\n", va01);
      printf("va02 = %D(20,5)\n", va02);
      printf("va03 = %D(31,20)\n", va03);
      printf("n    = %d\n", n);
      break;
    default:
      printf("Illegal case number : %d\n", whichcase);
  }

  va_end(arg_ptr);
}


int main(void) {
  int i = 168;
  decimal(10,2) pd01 = 12345678.12d;
  decimal(20,5) pd02 = -987.65d;
  decimal(31,20) pd03 = 12345678901.12345678900987654321d;
  int j = 135;

  vprnt(0, i, pd01, pd02, pd03, j);

  return(0);
}
}
#define _ISOC99_SOURCE
#include <stdio.h>                                       
#include <stdarg.h>	
void prnt(int max, ...);                                  
                                                          
int main(void)                                            
      {                                                   
       prnt(8, "0", "1", "1", "2", "3", "5", "8", "13");  
      }                                                   
                                                          
void prnt(int max, ...)                                   
    {                                                     
       va_list src;                                       
       va_list dest;                                      
       int args = 0;                                      
       char *fib[8];                                      
       va_start(src, max);                                
       va_copy(dest, src);                                
       while(args < max) {                                
         fib[args] = va_arg(dest, char *);                
         printf("fib[%d]:  %s  \n", args, fib[args++]);   
          }                                               
       va_end(dest);                                      
    }                                                     

Output

fib[0]:  0 
fib[1]:  1 
fib[2]:  1 
fib[3]:  2 
fib[4]:  3 
fib[5]:  5 
fib[6]:  8 
fib[7]:  13

Related information