Alex Rivera | Logout

Last named parameter not function or array?

Asked 2009-08-30T08:10:34.467
16

This question is about vararg functions, and the last named parameter of them, before the ellipsis:

void f(Type paramN, ...) {
  va_list ap;
  va_start(ap, paramN);
  va_end(ap);
}

I was reading in the C Standard, and found the following restriction for the va_start macro:

The parameter parmN is the identifier of the rightmost parameter in the variable parameter list in the function definition (the one just before the , ...). 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.

I wonder why the behavior is undefined for the following code

void f(int paramN[], ...) {
  va_list ap;
  va_start(ap, paramN);
  va_end(ap);
}

and not undefined for the following

void f(int *paramN, ...) {
  va_list ap;
  va_start(ap, paramN);
  va_end(ap);
}

The macros are intended to be implementable by pure C code. But pure C code cannot find out whether or not paramN was declared as an array or as a pointer. In both cases, the type of the parameter is adjusted to be a pointer. The same is true for function type parameters.

I wonder: What is the rationale of this restriction? Do some compilers have problems with implementing this when these parameter adjustments are in place internally? (The same undefined behavior is stated for C++ - so my question is about C++ aswell).

Edit
Report

1 Answer

1

C++11 says:

[n3290: 13.1/3]: [..] Parameter declarations that differ only in a pointer * versus an array [] are equivalent. That is, the array declaration is adjusted to become a pointer declaration. [..]

and C99 too:

[C99: 6.7.5.3/7]: A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. [..]

And you said:

But pure C code cannot find out whether or not paramN was declared as an array or as a pointer. In both cases, the type of the parameter is adjusted to be a pointer.

Right, so there's no difference between the two pieces of code you showed us. Both have paramN declared as a pointer; there is actually no array type there at all.

So why would there be a difference between the two when it comes to the UB?

The passage you quoted...

The parameter parmN is the identifier of the rightmost parameter in the variable parameter list in the function definition (the one just before the , ...). 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.

...applies to neither, as would be expected.

answered 2011-11-12T23:15:18.370

Your Answer