This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Different behaviour of stdarg as function of platform, is this a bug?
- To: Carlo Wood <carlo at alinoe dot com>
- Subject: Re: Different behaviour of stdarg as function of platform, is this a bug?
- From: Zack Weinberg <zack at wolery dot cumb dot org>
- Date: Wed, 7 Jun 2000 15:08:18 -0700
- Cc: gcc at gcc dot gnu dot org
- References: <20000607233403.A31184@a2000.nl>
On Wed, Jun 07, 2000 at 11:34:03PM +0200, Carlo Wood wrote:
> The gcc implementation of stdarg is such that the behaviour
> is different on different platforms.
>
> I am wondering what is the correct ANSI behaviour, and if
> gcc is conforming to this behaviour for all platforms or
> that this is a bug.
Your program does something which is not permitted by the C standard.
Section 7.15 paragraph 3 of C99 reads in part
[An object] ap [of type va_list] may be passed as an argument
to another function; if that function invokes the va_arg macro
with parameter ap, the value of ap in the calling function is
indeterminate and shall be passed to the va_end macro prior to
any further reference to ap.(212)
212) It is permitted to create a pointer to a va_list and pass
that pointer to another function, in which case the original
function may make further use of the original list after the
other function returns.
This section is quite badly written - not unusual for the C standard,
alas. Anyway, what they mean is that the only thing you can legally
do with vl after vfoo() returns is destroy it and recreate it. If you
had written
void foo(int x, ...)
{
int i;
va_list vl;
for(i = 0; i < 2; ++i)
{
va_start(vl, x);
vfoo(vl);
va_end(vl);
}
}
your program would be well-defined. C99 provides va_copy() which
could also be used in this context.
I think the footnote means you could get the ppc/linux behavior
reliably by writing
void vfoo(va_list *vl)
{
int a, b;
a = va_arg(*vl, int);
b = va_arg(*vl, int);
printf("vfoo: %d %d\n", a, b);
}
void foo(int x, ...)
{
int i;
va_list vl;
va_start(vl, x);
for (i = 0; i < 2; ++i)
vfoo(&vl);
va_end(vl);
}
but I would not do this in code intended to be portable.
zw