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