jv0l+@andrew.cmu.edu (Justin Chris Vallon) (05/12/88)
Is there any way to declare a function to have two arguments point to the same
place in the stack-frame? Let's say that I want to write the implementation of
foo which takes an optional argument based upon the first parameter:
{
char c;
int i;
short s;
long l;
foo(0); /* no optional argument */
foo(1, c); /* pass a character argument */
foo(2, i); /* pass an integer argument */
foo(3, s); /* pass a short arg */
foo(4, l); /* pass a long arg */
foo(5, "Hello world"); /* pass a char* arg */
}
Could this be done?
-Justin
justin.vallon@andrew.cmu.edugwyn@brl-smoke.ARPA (Doug Gwyn ) (05/12/88)
In article <cWW=o4y00XcRh2E04h@andrew.cmu.edu> jv0l+@andrew.cmu.edu (Justin Chris Vallon) writes: >Could this be done? Do it right -- use unions.
jnh@ece-csc.UUCP (Joseph Nathan Hall) (05/12/88)
In article <cWW=o4y00XcRh2E04h@andrew.cmu.edu> jv0l+@andrew.cmu.edu (Justin Chris Vallon) writes: >Is there any way to declare a function to have two arguments point to the same >place in the stack-frame? Let's say that I want to write the implementation of >foo which takes an optional argument based upon the first parameter: ... You can do this by a) using a variable-length argument list or b) passing your argument(s) in a union. Approach b) wastes a little space but is more conventional, hence more easily understood and probably easier to port between older compilers. -- v v sssss|| joseph hall || 201-1D Hampton Lee Court v v s s || jnh@ece-csc.ncsu.edu (Internet) || Cary, NC 27511 v sss || the opinions expressed herein are not necessarily those of my -----------|| employer, north carolina state university . . . . . . . . . . .
carroll@snail.CS.UIUC.EDU (05/13/88)
/* Written 3:43 pm May 11, 1988 by jv0l+@andrew.cmu.edu in snail:comp.lang.c */
/* ---------- "Args: var number & var types" ---------- */
Is there any way to declare a function to have two arguments point to the same
place in the stack-frame? Let's say that I want to write the implementation of
foo which takes an optional argument based upon the first parameter:
{
char c;
int i;
short s;
long l;
foo(0); /* no optional argument */
foo(1, c); /* pass a character argument */
foo(2, i); /* pass an integer argument */
foo(3, s); /* pass a short arg */
foo(4, l); /* pass a long arg */
foo(5, "Hello world"); /* pass a char* arg */
}
-Justin
justin.vallon@andrew.cmu.edu
/* End of text from snail:comp.lang.c */
union thing
{
char c;
int i;
short int s;
long int l;
char *q; /* in keeping with the 1 leter convention */
} ;
void foo(type,object)
int type; union thing *object;
/* pointer, although many compilers allow pass-by-value union/structs */
{
switch(type)
{
case 0 : putchar(object->c); break;
case 1 : printf("%d",object->i); break;
...
}
}
main()
{
union thing fudge;
foo(0,fudge.c='x',&fudge);
foo(1,fudge.i=17,&fudge);
...
/* this could be done with macro's, or better, just put the
value into fudge instead of whatever other var, and then
just call foo with foo(2,&fudge).
*/
}
Alan M. Carroll amc@woodshop.cs.uiuc.edu carroll@s.cs.uiuc.edu
Grad Student (TA) / U of Ill - Urbana ...{ihnp4,convex}!uiucdcs!woodshop!amc
"Too many fools who don't think twice
Too many ways to pay the price" - AP & EWchris@mimsy.UUCP (Chris Torek) (05/13/88)
In article <cWW=o4y00XcRh2E04h@andrew.cmu.edu> jv0l+@andrew.cmu.edu (Justin Chris Vallon) writes: [How would one implement a function foo such that ...] > foo(0); /* no optional argument */ > foo(1, c); /* pass a character argument */ > foo(2, i); /* pass an integer argument */ > foo(3, s); /* pass a short arg */ > foo(4, l); /* pass a long arg */ > foo(5, "Hello world"); /* pass a char* arg */ Doug Gwyn suggests using a union. This is likely to work (by which I mean more likely not to turn up implementation bugs and perhaps less likely to confuse programmers), but is inconvenient since C lacks aggregate constructors. Here is a sample foo(). /* K&R C */ /* NeoC */ #include <varargs.h> #include <stdarg.h> void void foo(va_alist) foo(int ind, ...) va_dcl { { va_list ap; va_list ap; int ind; char c; char c; int i; int i; short s; short s; long l; long l; char *cp; char *cp; va_start(ap); va_start(ap, ind); ind = va_arg(ap, int); /* now copy version on left verbatim */ switch (ind) { case NO_ARG: work0(); break; /* * nb: because char, short, and int are all extended to int, it * is probably unnecessary to distinguish between them. */ case CHAR_ARG: c = va_arg(ap, int); work1(c); break; case INT_ARG: i = va_arg(ap, int); work2(i); break; case SHORT_ARG: s = va_arg(ap, int); work3(s); break; case LONG_ARG: l = va_arg(ap, long); work4(s); break; case STR_ARG: cp = va_arg(ap, char *); work5(cp); break; } va_end(ap); } /* note that neo-C makes an annoying semantic change to va_start */ /* (NEVER change the semantics without changing the name! grr..) */ -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
karl@haddock.ISC.COM (Karl Heuer) (05/13/88)
In article <cWW=o4y00XcRh2E04h@andrew.cmu.edu> jv0l+@andrew.cmu.edu (Justin Chris Vallon) writes: >Is there any way to declare a function to have two arguments point to the >same place in the stack-frame? Let's say that I want to write [a function] >foo which takes an optional argument based upon the first parameter: ... > foo(0); /* no optional argument */ > foo(1, c); /* pass a character argument */ > foo(2, i); /* pass an integer argument */ > foo(3, s); /* pass a short arg */ > foo(4, l); /* pass a long arg */ > foo(5, "Hello world"); /* pass a char* arg */ Yes, it can be done, in at least two ways. Doug Gwyn has suggested using unions; this is awkward because (lacking a cast-to-union) you'd have to write junk like "un.u_asint = i; foo(2, un);". The other way is to use <stdarg.h> (on ANSI implementations) or <varargs.h> (if you've got it). In this case you don't declare the second argument at all, but instead fetch its value from the argument list via the va_arg macro. N.B. When function foo() handles cases 1 and 3, the argument type must be specified as "int", even if you want to store it in a smaller object: char c; ... c = va_arg(ap, int); Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
henry@utzoo.uucp (Henry Spencer) (05/14/88)
> Is there any way to declare a function to have two arguments point to the same > place in the stack-frame? ... Well, sort of. If you can make the problem printf-like, with earlier arguments of fixed types determining the variable-type arguments, then whatever method your implementation uses for printf should suffice. If your implementation has a <stdargs.h> header, use that. Second choice is <varargs.h>. If you have neither of those, it's still possible but the code will be highly implementation-specific and it's difficult to supply specific advice. Note that this is *not* a general way of having two arguments in the same location; to do that you have to use unions, and doing *that* portably requires that the caller know about it. -- NASA is to spaceflight as | Henry Spencer @ U of Toronto Zoology the Post Office is to mail. | {ihnp4,decvax,uunet!mnetor}!utzoo!henry