va_copy

L

Laurent Deniau

Is the following code valid:

void func(int va_flag, ...)
{
va_list va;
va_start(va, va_flag);

if (va_flag) { // indirect va_list
va_copy(va, va_arg(va, va_list));
}

// [...] code using va

va_end(va);
}

or it should absolutely be written as:

void func(int va_flag, ...)
{
va_list va;
va_start(va, va_flag);

if (va_flag) { // indirect va_list
va_list va0;
va_copy(va0, va_arg(va, va_list));
va_end(va);
va_copy(va, va0);
va_end(va0);
}

// [...] code using va

va_end(va);
}

According to the norm, only the second case is correct, otherwise va_end
would never be applied to the direct va if flag == 0. But the second
case is also more complex, even if in principle it should generate the
same code for a reasonable smart compiler (assuming va_end is a NOP).

a+, ld.
 
D

Dave Thompson

Is the following code valid:

void func(int va_flag, ...)
{
va_list va;
va_start(va, va_flag);

if (va_flag) { // indirect va_list
va_copy(va, va_arg(va, va_list));
}

// [...] code using va

va_end(va);
}

or it should absolutely be written as:

void func(int va_flag, ...)

<snip: use a temporary so it can va_end the one used to get the
caller-provided va_list before (copying and) using that>
According to the norm, only the second case is correct, otherwise va_end
would never be applied to the direct va if flag == 0. But the second
case is also more complex, even if in principle it should generate the
same code for a reasonable smart compiler (assuming va_end is a NOP).
Actually I don't think even the second is completely guaranteed, since
va_list can be any object type, even one which is modified by the
default argument promotions and so cannot be safely fetched by va_arg.
This isn't likely since it seems improbable that the information
needed for a va_list can be smaller than a data pointer which in turn
is rarely smaller than 'int', but I think it is permitted.

If va_flag is used only for this I would probably instead make it a
pointer to va_list which is either the address of the caller's va_list
= use (a copy of?) that or null = use my own variable arg list.
I think that's a clearer 'in-band' way of signalling the choice,
probably at least as efficient, and totally Standard.

Or just use the more common and arguably cleaner approach of having
e.g. a separate func (?,...) which forwards to vfunc (va_list).

- David.Thompson1 at worldnet.att.net
 
L

Laurent Deniau

Dave said:
Is the following code valid:

void func(int va_flag, ...)
{
va_list va;
va_start(va, va_flag);

if (va_flag) { // indirect va_list
va_copy(va, va_arg(va, va_list));
}

// [...] code using va

va_end(va);
}

or it should absolutely be written as:

void func(int va_flag, ...)


<snip: use a temporary so it can va_end the one used to get the
caller-provided va_list before (copying and) using that>
According to the norm, only the second case is correct, otherwise va_end
would never be applied to the direct va if flag == 0. But the second
case is also more complex, even if in principle it should generate the
same code for a reasonable smart compiler (assuming va_end is a NOP).

Actually I don't think even the second is completely guaranteed, since
va_list can be any object type, even one which is modified by the
default argument promotions and so cannot be safely fetched by va_arg.
This isn't likely since it seems improbable that the information
needed for a va_list can be smaller than a data pointer which in turn
is rarely smaller than 'int', but I think it is permitted.

If va_flag is used only for this I would probably instead make it a

Well, va_flag is not really there. I use a bit inside a required
argument. But the goal is the same, that is to apply the reverse pattern
of variadic function calling the va_list version. Instead, all such
functions are variadic and if the va_list version is required, then the
indirection bit must be set. I found this pattern more efficient than
the classic one.
pointer to va_list which is either the address of the caller's va_list
= use (a copy of?) that or null = use my own variable arg list.
I think that's a clearer 'in-band' way of signalling the choice,
probably at least as efficient, and totally Standard.

This is an option already studied, but I found some performance loss due
to the use of this indirection. And it does not solve the problem (if any).
Or just use the more common and arguably cleaner approach of having
e.g. a separate func (?,...) which forwards to vfunc (va_list).

This is an option that I cannot achieve for few reasons, one being
efficiency.

Thanks for your reply.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
474,109
Messages
2,570,671
Members
47,263
Latest member
SyreetaGru

Latest Threads

Top