Topic: variable args and args by reference


Author: O.Levillain@frcl.bull.fr (Olivier Levillain)
Date: 14 May 93 07:57:05 GMT
Raw View
As far as I know, most machine/compiler implements the va_start ANSI C feature as something
like:
 #define va_start(ARGLIST, FIRSTARG) (ARGLIST=&FIRSTARG some computation)
This means that you must take the address of the last argument that is not in the ellipsys.
So what about the address of an argument that has been passed by reference ? How can I get it ?

I tried the following piece of code with G++ on Mips Magnum machine :

#include <stdarg.h>
int f(int &x, ...)
{
  va_list args;
  va_start (args, x);
  int z=va_arg (args, int);
  printf ("result=%d\n", z);
}

main ()
{
  int x;
  f(x, 2);
}

and this was expanded by the preprocessor as:

# 1 "tt.cc"
# 1 "/usr/local/lib/g++-include/stdarg.h" 1 3
extern "C" {
# 1 "/usr/local/lib/gcc-lib/mips-mips-sysv/2.2.2/include/stdarg.h" 1 3
 # 1 "/usr/local/lib/gcc-lib/mips-mips-sysv/2.2.2/include/va-mips.h" 1
 typedef char * __va___list;
# 23 "/usr/local/lib/gcc-lib/mips-mips-sysv/2.2.2/include/stdarg.h" 2 3
# 68 "/usr/local/lib/gcc-lib/mips-mips-sysv/2.2.2/include/stdarg.h" 3
# 2 "/usr/local/lib/g++-include/stdarg.h" 2 3
}
# 1 "tt.cc" 2

int f(int &x, ...)
{
  __va___list  args;
  (args = ((char *) &( x) + (((sizeof ( x) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) )) ;
//             ------------
  int z=(( int *)(args = (char *) (__alignof( int) > 4 ? ((int)args + 2*8 - 1) & -8 : ((int)args + 2*4 - 1) & -4)))[-1] ;
  printf ("result=%d\n", z);
}

main ()
{
  int x;
  f(x, 2);
}

and, I CANNOT WORK !!!
So what ? Is it a bug in the G++ definition of va_start ? I don't think so.
I pointed out this problem because I really need to have the address of an argument that has been passed by
reference and I can't figure out how I can get it.

Sorry if this is a FAQ and thanks in advance to those who will reply.

  OLIVIER


-------- Olivier LEVILLAIN --- Bull S.A. --------------------------------
 DSE-LANG-ESAF               e-mail: O.Levillain@frcl.bull.fr
 Rue Jean-Jaures, F6/1D/05, BP 53    tel: (33-1) 30-80-65-52
 78340 Les Clayes-sous-Bois, France  Fax: (33-1) 30-80-79-50
-------------------------------------------------------------------------




Author: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Date: Sat, 15 May 1993 03:56:42 GMT
Raw View
O.Levillain@frcl.bull.fr (Olivier Levillain) writes:

>As far as I know, most machine/compiler implements the va_start ANSI C
>feature as something like:
> #define va_start(ARGLIST, FIRSTARG) (ARGLIST=&FIRSTARG some computation)
>This means that you must take the address of the last argument that is
>not in the ellipsys.  So what about the address of an argument that has
>been passed by reference ? How can I get it ?
>
>I pointed out this problem because I really need to have the address of
>an argument that has been passed by reference and I can't figure out
>how I can get it.

I think that what you want is not possible.
As a work-around you will need to make the first variable argument
part of the prototype. Thus instead of

 foo(int&, ...)

you need to write

 foo(int&, int, ...);
 foo(int&, double, ...);
 // ... and so on for every possible type of the first variable
 //     argument

Since the second parameter is passed by value, there is then no difficulty
use varargs.

--
Fergus Henderson                     This .signature virus might be
fjh@munta.cs.mu.OZ.AU                getting old, but you still can't
                                     consistently believe it unless you
Linux: Choice of a GNU Generation    copy it to your own .signature file!




Author: steve@taumet.com (Steve Clamage)
Date: Sat, 15 May 1993 23:46:21 GMT
Raw View
O.Levillain@frcl.bull.fr (Olivier Levillain) writes:

>As far as I know, most machine/compiler implements the va_start ANSI C feature as something
>like:
> #define va_start(ARGLIST, FIRSTARG) (ARGLIST=&FIRSTARG some computation)
>This means that you must take the address of the last argument that is not in the ellipsys.
>So what about the address of an argument that has been passed by reference ? How can I get it ?

It is up to the compiler implementor to supply a <stdarg.h> header
which works with the particular compiler.  You cannot reasonably expect
to take a header file or set of macros from one implementation and
expect it to work with another.

The reason the <stdarg.h> macros must be supplied by the compiler implementor
is that you cannot portably write them yourself.  In some implementations,
the macros expand to internal compiler function calls, for example.

--

Steve Clamage, TauMetric Corp, steve@taumet.com