on the fringe of C syntax/semantics

Chris Torek chris at mimsy.UUCP
Wed Oct 4 18:02:39 AEST 1989


In article <80100001 at bonzo> roy at bonzo.sts.COM writes:
>Here are a couple questions that come up in conjunction with using the
>'varargs' series of function calls.  When calling the va_arg()
>function, the 2nd parameter is supposed to be simply a type ....

va_arg is not a function.  va_arg is a macro or (in some compilers)
a `magic cookie' (in ANSI-conformant compilers, once the ANSI C standard
is a standard, va_arg will have to be a macro that is defined as a
magic cookie in these compilers).

>... how does it know what type you specified?

The usual definition of va_arg for conventional stack machines is
something like

	#define	va_arg(ap, type) (((type *)(ap += sizeof(type)))[-1])

Note in particular that the `type' argument must produce a new type
when suffixed with `*', so that `int' and `double' are legal, but
`void (*)(void)' is not.

>The second question is in conjunction with how to declare certain types.
>Things like 'int' and 'char *' are a piece of cake, but how about a good,
>general declaration for a function?

If you are trying to write `ANSI C' (which, again, does not yet exist;
we are all just assuming that it will work the way the proposed standard
describes), the short answer is `there is none'.  Every function pointer,
however, `fits in' every other function pointer, so you can obtain
a `pointer to function of no arguments returning int' and then cast
it to `pointer to function of one ``char *'' argument returning int'
and then call through the result:

foo(sometype firstarg, ...) {
	/*
	 * A typedef is required so that we can append `*' to
	 * get `pointer to pointer to function (args) returning ...'
	 */
	typedef int (*fn)(void);
	fn x;
	va_list ap;
	int first = 1;

	va_start(ap, firstarg);
	for (;;) {
		x = va_arg(ap, fn);
		if (x == NULL)
			break;
		if (first) {
			((int (*)(sometype))fn)(firstarg);
			first = 0;
		} else
			fn();
	}
	va_end(ap);
}

If all the `fn's will have the same (fixed) set of arguments, you
can simply

	typedef int (*fn)(type1, type2, type3);

and leave out all the casts.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris at cs.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.lang.c mailing list