// undefined behavior
void f(char const paramN[], ...) {
va_list ap;
va_start(ap, paramN);
va_end(ap);
}
As far as i can see, that's just a parameter with type "char const*". What's
the reason of treating it different? 7.15.1.4/4 in n1256:
"If the parameter parmN is declared with the register storage class, with a
function or array type, or with a type that is not compatible with the type
that results after application of the default argument promotions, the
behavior is undefined."
What about function or arrays? Is there some old implementation that
actually behaved in some strange way?
paramN is not an array. It is a pointer. Also note that "function
type" does not include function pointer type.
REH
paramN is not an array, but it's *declared* with an array type. The
declaration is "adjusted" to a pointer type as per 6.7.5.3#7; but since the
adjusted type of a parameter never is an array or function type, obviously
that paragraph talks about the type before the adjustment, not after.
I suppose the point is that va_start has to be implemented with some
kind of compiler magic, and that magic might take place *before* the
parameter "char const paramN[]" is adjusted to "char const *paramN".
I don't know whether there are (or were) any implementations for which
this would be an issue.
Since the behavior is undefined, implementers can just ignore the
issue (and it will probably just work anyway), and programmers can
just use an explicit pointer declaration in this context.
The problem is that someone might write
void f(char const paramN[], ...) { ... }
and have it work "correctly" without a diagnostic, and then fail when
ported to some other system.
--
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"
It seems like a silly restriction, but here's a guess about why
the restriction is there.
A simple-minded implementation could use the address of the
parameter plus the 'sizeof' the type of the parameter to get the
address of the first additional argument. Depending on how these
are done inside the compiler, either or both might yield wrong
answers, because of the way '&' and 'sizeof' are defined for
function and array types.
I grant you, it would have to be a pretty naive implementation
to use such an approach, especially since the expression
(sizeof parmN + (char*) &parmN), written in plain code --
perhaps inside the macro definition -- is going to do the right
thing. But that's now, when we have the benefit of a
well-written and carefully specified treatment of varying
argument lists. In earlier days, perhaps even pre-ANSI, it
might not have been so obvious, and to accommodate some
earlier implementation (which may have been using one of
the precursors to stdarg.h) this restriction may have been
thrown in.