Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Variable argument list passed to another function. Where to put va_end?

0 views
Skip to first unread message

DSF

unread,
Feb 1, 2010, 7:34:53 PM2/1/10
to
Hello,

While working on a couple of functions that take a variable argument
list, I discovered they were almost completely identical, except for
one line of code. What a great situation for splitting off the common
code to a common function.

Now I know that va_start must be in the function that receives the
variable number of arguments, but must va_end be there as well?

In other words: In pseudo code,

int foo1(char *str, ...)
{
va_list ap;
int ret;

va_start(ap, str);

ret = foocommon(str, ap);
va_end(ap);

return ret;
}

int foo2(char *str, ...)
{
va_list ap;
int ret;

/* code unique to foo2 goes here */

va_start(ap, str);

ret = foocommon(str, ap);
va_end(ap);

return ret;
}

int foocommon(va_list ap)
{
/* handle va_arg here */
return foocommon status value;
}

Or can va_end be placed in foocommon, allowing foo1 and foo2 to end
with return foocommon(str, ap); ?

DSF

Kaz Kylheku

unread,
Feb 1, 2010, 8:06:48 PM2/1/10
to
On 2010-02-02, DSF <nota...@address.here> wrote:
> Hello,
>
> While working on a couple of functions that take a variable argument
> list, I discovered they were almost completely identical, except for
> one line of code. What a great situation for splitting off the common
> code to a common function.
>
> Now I know that va_start must be in the function that receives the
> variable number of arguments, but must va_end be there as well?

The 1999 ISO C standard says, in section 7.15.1, that ``Each invocation of the
va_start or va_copy macros shall be matched by a corresponding invocation of
the va_end macro in the same function.''

Moreover ``The va_end macro facilitates a normal return from the function ...''.

If you have va_start in a function, you can't make a tail call to the common
function, since you haven't used va_end to facilitate a normal return.

Peter Nilsson

unread,
Feb 1, 2010, 8:06:56 PM2/1/10
to
DSF <notava...@address.here> wrote:
> ...I know that va_start must be in the function that receives

> the variable number of arguments, but must va_end be there as
> well?

Yes. N1336, 7.15.1p1, "...Each invocation of the va_start and


va_copy macros shall be matched by a corresponding invocation
of the va_end macro in the same function."

--
Peter

Keith Thompson

unread,
Feb 1, 2010, 8:32:17 PM2/1/10
to

N1336 is an early draft of C201X, and has no real official standing.

However N1256 7.15.1p1 has the same wording.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Nobody

unread,
Feb 1, 2010, 8:57:55 PM2/1/10
to
On Mon, 01 Feb 2010 19:34:53 -0500, DSF wrote:

> While working on a couple of functions that take a variable argument
> list, I discovered they were almost completely identical, except for
> one line of code. What a great situation for splitting off the common
> code to a common function.
>
> Now I know that va_start must be in the function that receives the
> variable number of arguments, but must va_end be there as well?

Yes.

> Or can va_end be placed in foocommon, allowing foo1 and foo2 to end
> with return foocommon(str, ap); ?

No.

7.15.1p1:

> Each invocation of the va_start or va_copy macros shall be matched by a
> corresponding invocation of the va_end macro in the function accepting a
> varying number of arguments.


DSF

unread,
Feb 2, 2010, 1:20:20 AM2/2/10
to
On Mon, 01 Feb 2010 19:34:53 -0500, DSF <nota...@address.here>
wrote:

To all who answered:

That's what I figured. I just wanted to make sure.

Thanks!

DSF

Tim Rentsch

unread,
Feb 4, 2010, 1:40:28 PM2/4/10
to
Kaz Kylheku <kkyl...@gmail.com> writes:

That's true. But it's easy enough to put the tail call one
function down, and everything's copacetic. As a general
rule functions that use va_start/va_end should be written
as simple wrappers, calling an inner function that does
the real work.

0 new messages