- Forward


Variadic Functions in C
An Introduction


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu

Print

Background
Back SMYC Forward
  • "Normal" Functions:
    • Have a fixed and known number of formal parameters
    • The type of each parameter is known
  • Variadic Functions:
    • Have one or more typed formal parameters
    • Have an unknown number of untyped formal parameters
Some Important Distinctions
Back SMYC Forward
  • Functions with no formal parameters:
    • The number of actual parameters is unspecified and any number can be passed, but they will be ignored
  • Functions with a void formal parameter:
    • There can be no actual parameters
  • Variadic functions:
    • The number of actual parameters is variable and they can be used
Syntax of Variadic Functions
Back SMYC Forward
  • Declaration:
    • type name(type name, [type name,]... ...
    • Example: int max(int a, int b, ...)
  • "Typical" Invocation:
    • Identical to "normal" functions but with a sentinel to indicate the last parameter
    • Example: max(10, 5, 13, 7, 9, -1)
  • "Clever" Invocation:
    • Use one of the parameters (often a char array) to provide information about the number of other parameters
    • Example: printf("%d %d %d %d %d", 10, 5, 13, 7, 9)
Support for Variadic Functions
Back SMYC Forward
  • The Header File:
    • <stdarg.h>
  • The Macros:
    • va_list: Data type
    • void va_start(va_list ap, type last_fixed): Initialize the argument pointer
    • type va_arg(va_list ap, type): Return the next argument (and update ap)
    • void va_end(va_list ap): Clean up
    • void va_copy(va_list destination, va_list source)
An Example
Back SMYC Forward
cexamples/variadic/extremes.c
 
Implementations
Back SMYC Forward
  • Use a Pointer to the Stack Frame:
    • typedef char *va_list; #define va_start(ap, v) (ap=(va_list) _ADDRESSOF(v) + _INTSIZEOF(v)) #define va_arg(ap, t) (*(t *)((ap += _INTSIZEOF(t)) - INTSIZEOF(t))) #define va_end(ap) (ap = (va_list)0)
    • Note: Whether addresses increase or decrease depends on the way the stack is organized.
  • Use an Array of Pointers:
    • Where the array is of length 1
  • Use Registers:
    • va_start() then allocates memory and va_end() later frees memory
There's Always More to Learn
Back -