Path: utzoo!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!wuarchive!udel!haven!mimsy!chris From: chris@mimsy.umd.edu (Chris Torek) Newsgroups: comp.lang.c Subject: Re: Arrays of functions - calling them with different number of args. Message-ID: <22975@mimsy.umd.edu> Date: 8 Mar 90 10:57:45 GMT References: <8553@cbnewsh.ATT.COM> <22954@mimsy.umd.edu> <4410@daffy.cs.wisc.edu> Distribution: na Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 83 >>In article <8553@cbnewsh.ATT.COM> ijk@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@mimsy.umd.edu> I wrote about how this cannot be done in ANSI C. In article <4410@daffy.cs.wisc.edu> schaut@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, ...) { } is not type-compatible with int bar(char *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@cs.umd.edu Path: uunet!mimsy!chris