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