passing variable arguments

Steve Summit scs at adam.mit.edu
Tue Jun 12 11:41:05 AEST 1990


This topic is discussed in the frequently-asked questions list
(question 25 in the June posting).  Additionally, Tim McDaniel
posted a number of corrections and explanations, in article
<MCDANIEL.90Jun9154616 at angler.amara.uucp>, to some previously-
posted code.

In article <314 at ndla.UUCP> platt at ndla.UUCP (Daniel E. Platt) writes:
>...
>	/* get a pointer to the stack */
>	...
>C is set up to put the first argument on the top of the 'stack' (if
>there is one).

...but there might not be one, and even if there is one there is
no guarantee how it might be set up, which is why...

>...this isn't portable.  There are macro standards set up to handle this
>called 'varargs.'

The new, standard macro package (ANSI C) is called <stdarg.h>.
Don't try to pick arguments apart "by hand;" use the standard
macro package.  If your compiler doesn't supply it yet, you may
be able to make use of someone else's implementation of stdarg.h .
This is not guaranteed to work, as the innards of a standard
header may be tied to a particular implementation (particularly
for something as machine-dependent as variable-length argument
lists), but it is possible to write a semiportable stdarg.h that
will work anywhere a "standard" macro-only (i.e. no special-cased
compiler support) varargs.h would work.  I posted one to
alt.sources some time ago.  An amended version is attached.

(If stdarg.h is not an option, you could also try using the old
varargs package, with which stdarg is partly compatible).

                                            Steve Summit
                                            scs at adam.mit.edu

----8<------8<----cut here for simple stdarg.h----8<------8<-----
/*
 *  stdarg implementation for "conventional" architectures with
 *  downward-growing stacks.  The stack is assumed to be aligned
 *  to word, i.e. int, sized boundaries, with smaller arguments
 *  widened when passed and larger arguments equal to (or rounded
 *  up to) a multiple of the word size.
 *  Note that this code (and indeed, any simple macro-based
 *  approach) cannot possibly work on architectures which pass
 *  arguments in registers.
 *
 *  Another problem is that it doesn't (and can't, without help
 *  from the compiler) know that float arguments are widened to double
 *  when passed.  Don't, therefore, call va_arg(..., float).
 *
 *  Steve Summit  4/15/89
 *
 *  This code is Copyright 1989 by Steve Summit.
 *  It may, however, be redistributed and used without restriction.
 */

typedef int __stacktype;
typedef char __argptype;
typedef __argptype *va_list;

#define __argsize(thing) ((sizeof(thing) + (sizeof(__stacktype) - 1)) \
	/ sizeof(__stacktype) * (sizeof(__stacktype) / sizeof(__argptype)))

#define va_start(vaptr, lastarg) \
			vaptr = (va_list)&lastarg + __argsize(lastarg)

#define va_arg(vaptr, type) \
		(*(type *)(((vaptr) += __argsize(type)) - __argsize(type)))

#define va_end(vaptr)



More information about the Comp.lang.c mailing list