varargs function, is this legal?

E

Edward Rutherford

Hello:

void myfunc(char * format, int param1, ...)
{
va_list argp;

va_start(argp, format);
#if CONDITION
some code involving param1
#endif
some code that uses format and argp
va_end(argp);

}

The obvious thing being that the function in question, under certain
build configurations, needs to snoop the first varargs parameter.
I've seen the comment made on various pages about varagrs that the
second parameter to va_start is the last named parameter of the
function, but is this a hard requirement?

The reason I'm curious is that when heavily optimized, when CONDITION
evaluates false, MS VC 2005's compiler will optimize out the
evaluation of param1 since it's not actually used in the function.
This in turn causes all sorts of hell because the parameters fetched
via argp don't line up properly.

Compiler bug, or am I breaking the law?
 
K

Kaz Kylheku

Hello:

void myfunc(char * format, int param1, ...)
{
va_list argp;

va_start(argp, format);
#if CONDITION
some code involving param1
#endif
some code that uses format and argp
va_end(argp);

}
Compiler bug, or am I breaking the law?

Breaking the law. The only way I can think of to do this is:

void myfunc(char * format, ...)

and use use va_arg (argp, int) to extract the first parameter.

To be sure that the parameter is there, assume that the parameters match the
format string (which they have to for any of this to be correct), and parse ito
the format string. If the first conversion you find is the one that you're
looking for, then extract.

You can va_end and re-initialize the va_list with another va_start:

va_list argp, argp_cp;

va_start (argp, format);
/* Maybe extract va_arg(argp, int), depending on contents of format. */
va_end (argp);

va_start (argp, format); /* start again */
/* ... some code that uses format and argp ... */
va_end (argp);

(In a function where you are not calling va_start yourself (because you already
received a va_list as an argument) you can implement similar logic with the
help of va_copy to save the original argument list. va_copy is a C99 feature.)
 
L

Lew Pitcher

Breaking the law. The only way I can think of to do this is:

void myfunc(char * format, ...)

and use use va_arg (argp, int) to extract the first parameter.

Wouldn't
void myfunc(char * format, int param1, ...)
{
va_list argp;

va_start(argp, param1); /* Note: use param1 instead of format */
#if CONDITION
some code involving param1
#endif
some code that uses format and argp
va_end(argp);

}
suffice?

7.15.1.4 The va_start macro
Synopsis
#include <stdarg.h>
void va_start(va_list ap, parmN);
Description
The va_start macro shall be invoked before any access to the unnamed
arguments.

The va_start macro initializes ap for subsequent use by va_arg and va_end.
va_start (or va_copy) shall not be invoked again for the same ap without
an intervening invocation of va_end for the same ap.

The parameter parmN is the identiï¬er of the rightmost parameter in the

variable parameter list in the function deï¬nition (the one just before
the , ...).
....
 
K

Kaz Kylheku

Wouldn't
void myfunc(char * format, int param1, ...)
{
va_list argp;

va_start(argp, param1); /* Note: use param1 instead of format */
#if CONDITION
some code involving param1
#endif
some code that uses format and argp
va_end(argp);

}
suffice?

That was my initial reaction too, but the problem is that the resulting
va_list then excludes param1 which is presumably needed by the format string in
"some code that uses format and argp" (e.g. a call to vfprintf).
 
E

Eric Sosman

Hello:

void myfunc(char * format, int param1, ...)
{
va_list argp;

va_start(argp, format);
#if CONDITION
some code involving param1
#endif
some code that uses format and argp
va_end(argp);

}

The obvious thing being that the function in question, under certain
build configurations, needs to snoop the first varargs parameter.
I've seen the comment made on various pages about varagrs that the
second parameter to va_start is the last named parameter of the
function, but is this a hard requirement?

Yes: 7.16.1.4p4, also 7.16p2.
The reason I'm curious is that when heavily optimized, when CONDITION
evaluates false, MS VC 2005's compiler will optimize out the
evaluation of param1 since it's not actually used in the function.
This in turn causes all sorts of hell because the parameters fetched
via argp don't line up properly.

Compiler bug, or am I breaking the law?

You are most definitely breaking the law by passing `format'
instead of `param1' to va_start.

Perhaps if you revealed the details of "some code involving
params" and "some code that uses format and argp" someone might
have a constructive suggestion about your problem, whatever it
might be.
 

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

Forum statistics

Threads
473,744
Messages
2,569,479
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top