dave@cs.arizona.edu (David P. Schaumann) (03/13/90)
I want to write a routine that uses variable number of args that passes
*all* of it's args to another routine. I tried this:
int s( size, va_alist )
int size ;
va_dcl
{ t( size, va_alist ) ; }
int t( size, va_alist )
int size ;
va_dcl
{ int i ;
va_list ap ;
/* do some stuff with va_alist */
}
Unfortunately, when I do this, only the first value in va_alist is right.
Everything else is garbage. Anybody know how to fix this?
Thanx, Dave
dave@cs.arizona.edu
ping@cubmol.bio.columbia.edu (Shiping Zhang) (03/13/90)
In article <136@caslon.cs.arizona.edu> dave@cs.arizona.edu (David P. Schaumann) writes: >I want to write a routine that uses variable number of args that passes >*all* of it's args to another routine. I tried this: > > int s( size, va_alist ) > int size ; > va_dcl ^^^^^^ This is the trick point. I guess the types of your args are also varied at different calls to this routine. If I'm right, then you need using union to deal with this problem. Just define an union with all possible used data types in it. Then declare an array of this union, and put your args in this array and use it as the args list. -ping
chris@mimsy.umd.edu (Chris Torek) (03/13/90)
In article <136@caslon.cs.arizona.edu> dave@cs.arizona.edu (David P. Schaumann) writes: >I want to write a routine that uses variable number of args that passes >*all* of it's args to another routine. This cannot be done (portably). That is, given a function that takes the same arguments as, say, printf: #include <stdarg.h> int foo(char const *fmt, ...); and an actual call: foo("%d %s %lu\n", 1, "2", 3LU); and an implementation of foo: static int nfoo; /* count of calls to foo */ /* foo: just like printf, except that it counts total calls */ int foo(char const *fmt, ...) { nfoo++; /* now we want to call printf() to actually do it */ <??? what goes here ???> } there is *nothing* you can put for the <???> line that will always work, no matter how many arguments are passed to foo, etc. There is, however, a solution. While it is impossible to call printf(), it is not impossible to achieve the same effect. There are two ways to do it: parse the format directly (within foo()), or---much simpler ---get in your DeLorean Time Machine, go back in time, and decree that printf() also comes with vprintf(). I have done the latter for you%, so instead of the <???> line, we can write: int foo(char const *fmt, ...) { int ret; va_list ap; nfoo++; /* count another call to foo */ va_start(ap, fmt); /* get info on arguments */ ret = vprintf(fmt, ap); /* and then do a printf */ va_end(ap); /* clean up */ return ret; } Note that, to do this, we MUST have TWO versions of every `varargs'- brand function: one that takes a literal variable argument list (with a `...' prototype), and one that takes the `varargs info' thing set up by va_start(). Indeed, the implementation of the `...' version is simply a call to the `va_list' version---printf() can look exactly like foo() above, minus the `nfoo++' line. ----- % Just kidding. Actually, my time machine is in the shop today, getting the brakes relined. :-) (Now I wonder if this will get the Bill Wolfe award for frivolity in exposition. :-) ) ----- For Classic C compilers, the only change is that the prototypes go away and the function itself changes a bit: int foo(va_alist) va_dcl { char *fmt; int ret; va_list ap; va_start(ap); fmt = va_arg(ap, char *); ret = vprintf(fmt, ap); va_end(ap); return ret; } Note that, to be Officially Correct, the `fmt = va_arg(ap, char *)' line is necessary---you are Not Allowed to write int foo(fmt, va_alist) char *fmt; va_dcl { <...code...> } (Although this happens to work on every machine I have used, and it makes a better analogy to the new stdarg code, and I like it better myself and wish that it *were* Offically Correct, it is not; avoid this temptation. Write the ugly extra assigments. Someday you will be glad you did.) Summary: do not try to pass your arguments to another varargs function; instead, pass your va_list object to a *different*, non-varargs function: one that does what the varargs function does, but takes a va_list object. If there is no such function, rewrite the code so that there is. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
dave@cs.arizona.edu (David P. Schaumann) (03/15/90)
Thanx to everybody who replied. I now have >400 lines of replies via email & news to sift through & try to (mentally) digest. If you are thinking of adding your 2 cents, please don't email ME. I have as much info on this as I need. Anyone who wishes to take this up as a general discussion is welcome to... Again, thanx to all who sent replies. Dave Schaumann dave@cs.arizona.edu