Variable length argument list handling

Ben Jones bjones at esunix.UUCP
Thu Aug 17 08:19:57 AEST 1989



This  discussion  relates  to the handling of variable length argument 
lists in C.

Question:  Why can't a C function which allows a  variable  number  of
arguments find out how many arguments were actually passed?

The ANSI standard for C as described in K&R-2 includes  a  method  for
using  a  variable number of arguments in a function call ("stdarg.h")
which  is  similar  to  other  methods  currently  in  use  (such   as
"varargs.h")  but  makes  no  provision  for  obtaining  the number of
arguments.  We are dependent on the caller specifying something in the
first  argument which indicates how many arguments are to follow, like
the format string in "printf".

The VAX/VMS  version  of  "varargs.h"  provides  for  a  macro  called
"va_count" which obtains the number of longwords in the argument list.
This is not quite a parameter count but it is probably the  best  that
can  be  done  since  parameter  lists  can  have  mixed  integer (one
longword) and floating point (two longwords) arguments.  In any  case,
this  feature  is  available  on the VAX because the procedure calling
standard requires a  parameter  list  to  start  with  the  number  of
longwords.   In  fact, the CALLS instruction uses this standard to pop
the parameter list off the  stack  automatically  when  the  procedure
returns.

Most other processors don't have anything special  when  it  comes  to
procedure  calling  and  so  it  is  entirely  up  to the software how
procedures are called.  Compilers for RISC processors  generally  pass
the  first  several  arguments in registers for the sake of efficiency
and they may have their choice of separate floating point and  integer
registers.   This  complicates  the  use  of  variable  argument lists
because the function itself must know what  possible  combinations  of
registers  and  stack frame variables may be utilized by the caller of
the function.

It may be possible to fake a "va_count" on those  processors.   Sun  3
has  an  instruction following the function call which pops the stack.
Sun 4 and MIPS do not pop the stack but they  consistently  store  the
last  actual  parameter  in  the instruction preceeding the call.  The
"va_count" function  would  have  to  do  some  instruction  decoding.
Still,   it   would  be  preferable  to  come  up  with  a  clean  and
non-implementation dependent mechanism.

ANSI C does not change any of the function  calling  conventions.   It
cannot  or  else existing function libraries would be invalidated when
switching to ANSI C.  Therefore, it would appear that the best way  to
get  the  length of the argument list is to add a new reserved word to
the language to handle variable parameter lists.

       -------------------------------------------------------

Just in case nobody has thought of anything better, consider offer the
following suggestion:


A function is declared the same as it is in ANSI C  but  using  a  new
reserved name:

    type funct(var_arguments);

         When "var_arguments" occurs in  a  function  declaration,  it
         indicates  that  when the function is called, parameters will
         be passed on the stack with the top of the  stack  containing
         the size of the parameter list.  Otherwise, parameters are to
         be passed according to whatever convention is currently used.

Inside the  function  code,  an  internal  pointer  of  some  sort  is
initialized  upon entry.  The following reserved functions can be used
within the body of a variable function to obtain the actual arguments:

    var_start();

         Reset the internal pointer to the start of the argument list.
         This   should  be  the  first  executable  statement  in  the
         function.


    var_arg(type)

         Get the next element  and  <type>  cast  it.   Increment  the
         internal  pointer  appropriately.  If the end of the argument
         list has been reached, trap to an error handler.


    var_count(type)

         Return the count of the number of elements remaining assuming
         that  they  are  all  of  a  certain  <type>.   Each  call to
         "var_arg" reduces this count appropriately.

For example:

    /*  <value> = maximum(p1,p2,p3,...)                 */
    /*      Return the argument with the highest value  */

    double maximum(var_arguments)
    {
    double m;
        var_start();
        m = var_arg(double);
        while (var_count(double)) m = max(m,var_arg(double));
    }


Ben Jones
Evans & Sutherland Computer Corporation
600 Komas Drive Salt Lake City, Utah 84108
(801)-582-5847 x3361
{decwrl ! utah-cs}!esunix!bjones



More information about the Comp.lang.c mailing list