va_copy

R

REH

Is there a standard when to implement va_copy in the pre-99 standard? Is
this allowed by the standard:

#define va_copy(DEST, SRC) memcpy((DEST), (SRC), sizeof(va_list))


Thanks.
 
B

Ben Pfaff

REH said:
Is there a standard when to implement va_copy in the pre-99 standard? Is
this allowed by the standard:

#define va_copy(DEST, SRC) memcpy((DEST), (SRC), sizeof(va_list))

It's not obvious to me why that couldn't be a conforming
implementation of va_copy. However, I wonder whether you really
mean "can I implement it this way?" In general, no: there is no
guarantee that this will have the desired effect.
 
C

Chris Torek

It's not obvious to me why that couldn't be a conforming
implementation of va_copy.

Well, almost:

#define va_copy(dst, src) \
((void) memcpy((dst), (src), sizeof(va_list)))

because C99 says that, while va_copy is a macro, it acts as if it
were a void-valued function.
However, I wonder whether you really mean "can I implement it this
way?" In general, no: there is no guarantee that this will have
the desired effect.

Indeed. In particular, it will not work on implementations in
which "va_list" is a typedef alias for "char *", such as most
Intel-x86 systems.

There is always some way to define va_copy() that will work, but
the actual definition needs to change from one platform to the next.
The two most common definitions are the memcpy above, and the
even simpler:

#define va_copy(dst, src) ((void)((dst) = (src)))

Without knowing how the compiler implements va_list, va_start, etc.,
it is impossible to tell which of these two common definitions will
work (or whether a different, uncommon, definition is required).
 
P

Peter Nilsson

Chris said:
Well, almost:

#define va_copy(dst, src) \
((void) memcpy((dst), (src), sizeof(va_list)))

because C99 says that, while va_copy is a macro, it acts as if it
were a void-valued function.

How would a strictly conforming program tell the difference?
 
C

Chris Torek

Chris said:
[I inserted a (void) cast in a memcpy()]
... C99 says that, while va_copy is a macro, it acts as if it
were a void-valued function.

How would a strictly conforming program tell the difference?

This is a bit of an odd situation, really.

Without the cast, you could feed an "invalid" translation unit --
one that requires a diagnostic, that is -- to a compiler and perhaps
get no diagnostic:

void vfunc(const char *fmt, ...) {
va_list va1, va2;

va_start(fmt, va1);

void *p = va_copy(va1, va2);
/* more code here */
}

But a compiler is always free to emit bogus diagnostics, so even
if we remove the "void *p =" part, we could still get a diagnostic.

This means there is no *guaranteed* way to discover that va_copy()
is mis-#defined, and we cannot write a strictly conforming program
to find out.

Still, whenever we (C programmers) play the role of "implementor",
writing some or all of a C compiler, we should at least strive to
give useful diagnostics. Defining va_copy without the (void) cast
will usually omit the useful diagnostic, and -- depending on the
compiler -- might even omit the required one.
 

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

Members online

No members online now.

Forum statistics

Threads
474,160
Messages
2,570,889
Members
47,420
Latest member
ZitaVos505

Latest Threads

Top