Re: How to call functions with variable number of arguments?



On Jul 29, 10:04 am, Amitava <ad_...@xxxxxxxxx> wrote:
On Jul 29, 11:55 am, Eric Sosman <Eric.Sos...@xxxxxxx> wrote:



This is Question 15.12 in the comp.lang.c Frequently Asked
Questions (FAQ) list at <http://www.c-faq.com/>, and the answer
might not please you.

--
Eric.Sos...@xxxxxxxx Hide quoted text -

Thanks for the pointer.

It's what I was suspecting (that is to say you guessed right)
but I was hoping the fine folks that prowl here could have
some MagicK up their sleeves.

There are various hackish ways to accomplish this.

- If myfunc is relatively simple, it could be turned into a macro
using the C99 variadic macro feature:

#define myfunc(k1, ...) (libfunc1(sin(k1), __VA_ARGS__)
+libfunc2(cos(k1), __VA_ARGS__)

If the function is a bit more complicated, you could combine this with
GCC's "statement expressions" extension:
#define myFunc(k1, ...) ({ \
float f1, f2; \
double d1, d2; \
int k2; \
f1 = compute_something(k1); \
d1 = compute_something_else(k1); \
f2 = libFunc1(f1, __VA_ARGS__); \
d2 = libFunc2(d1, __VA_ARGS__); \
k2 = compute_some_more(f2,d2); \
k2 })

Both of these will lose if they are called with arguments involving
side effects, e.g. myfunc(3, a++), since you have to use __VA_ARGS__
twice. You can avoid this for k1 by using a temporary variable but
not for the extra arguments.

- If you only need to support one or two systems, this would not be
terribly hard to do in assembly language.

- If the arguments are of a fairly simple form, you could do something
where you handle each possible case separately. For example, if they
are all floats with the last one zero, you could:

int myfunc(int k1, ...) {
va_list ap;
float args[100];
int i = 0;
va_start(ap, k1);
for (i=0; i < 100 && (args[i] = va_arg(ap, float)) != 0.0; i++) ;
if (i == 100) abort();
switch (i) {
case 0: d2 = libFunc1(d1, args[0]); break;
case 1: d2 = libFunc1(d1, args[0], args[1]); break;
case 2: d2 = libFunc1(d1, args[0], args[1], args[2]); break;
/* ... */
case 99: libfunc1(d1, args[0], args[1], skip a few, args[99]);
break;
}
more_stuff();
}

Of course someone might call myfunc with more arguments than you
planned for, but you could handle a really big number, at some cost in
code size and compiler stress. You can generate the switch statement
with a script or a fancy editor macro.

- If you have the source to libFunc1, you can steal it and make your
own version which takes a va_list as an argument.

More specifics about the problem might be helpful.
.



Relevant Pages