Arrays of functions - calling them with different number of args.

Chris Torek chris at mimsy.umd.edu
Thu Mar 8 20:57:45 AEST 1990


>>In article <8553 at cbnewsh.ATT.COM> ijk at cbnewsh.ATT.COM (ihor.j.kinal)
asks about ways to call functions (via a table of pointers) with differing
(but always fixed) argument lists.

>In article <22954 at mimsy.umd.edu> I wrote about how this cannot be done
in ANSI C.

In article <4410 at daffy.cs.wisc.edu> schaut at cat9.cs.wisc.edu (Rick Schaut)
writes:
>If all you want is a way to prototype the functions,
>	sometype (*action_tbl)[SIZE](type1 arg1,...);
>will do nicely.  This does sacrifice type checking on the second argument,
>but I get the impression this is not an important consideration.

This does more than sacrifice type checking on second and further arguments:
It also requires that every function called via the table be changed.  In
particular,

	int foo(char *p, ...) { <code using p> }

is not type-compatible with

	int bar(char *p) { <same code using p> }

Indeed, these are the most likely to differ in current implementations.
That is, given

	int (*p)();	/* old-style declaration */
	extern int fn(char *, double);
	p = fn;		/* set p to point to some function returning int */
	(*p)("foo", 2.71828);

the compiler will probably generate code that works.  However, given

	int (*p)();	/* old-style declaration, again */
	extern int fn(char *, ...);
	p = fn;
	(*p)("foo", 2.71828);

the compiler may well generate code that fails.

[ijk]
>>>What I really want is to construct an arg list and pass that to my
>>>function call, but I can't figure how to do that.

[chris]
>>There is no such option.  It would be nice, but it does not exist.

>If the compiler is ANSI compliant, then there is, indeed, a portable and
>standard way to implement this.  In fact, the ANSI version of printf is
>implemented using a variable-length argument list.  For further reference,
>see K&R, 2nd Ed. Sect. 7.3 (page 155).

This is not the same thing: this is passing a variable argument list to
a function known to take a variable argument list; what Ihor Kinal
described is constructing a fixed argument list to pass to a function
known to take a fixed argument list.  That is, in some C-like language
with this augmentation, we might write:

	fa_start(&argmagic);
	switch (tab[i].arg) {
	case NO_ARGS:
		break;
	case ONE_INT_ARG:
		fa_addarg(&argmagic, arg1, int);
		break;
	case ONE_INT_ARG_THEN_ONE_DOUBLE_ARG:
		fa_addarg(&argmagic, arg1, int);
		fa_addarg(&argmagic, arg2, double);
		break;
	default:
		panic("unknown arg type: tab[%d].arg = %d", i, tab[i].arg);
		/* NOTREACHED */
	}
	fa_invoke(tab[i].function, &argmagic);
	fa_end(&argmagic);

Summary: a prototype with a `...' is not compatible with a declaration
without a `...', and vice versa.  To use a variable argument list requires
changing all the existing code (something ijk asked to avoid).
-- 
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