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.edu
gwyn@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 & EW
chris@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