On Sun, 28 Sep 2003, Tuomo Valkonen wrote:

> Does this patch really fix something that is a problem in Ion's code?

Maybe not, but it's a lot harder to change the semantics of the C
language. You could also say that va_list shouldn't be an array, but many
binaries probably depend on that already, thus making it difficult to
change.

> Why does passing a pointer to a copy of a va_list work if passing a
> pointer to the original va_list doesn't?

On powerpc and s390, a va_list is an array. If you pass an array as an
argument to a function, it gets coerced into a pointer. The latter is
documented in K&R's "The C Programming Language" so it's not likely a gcc
bug. When you va_copy the coerced va_list, the copy becomes an array
again.

So, what's the difference between a pointer and an array and how does it
affect your code? I wrote an example to illustrate:

typedef int array[3];
void coerce(array x)
{
        printf("x = %x, &x = %x, *(void **)&x = %x\n", x, &x, *(void **)&x);
}
int main(int argc, char *argv[])
{
        array x = { 1, 2, 3 };
        printf("x = %x, &x = %x, *(void **)&x = %x\n", x, &x, *(void **)&x);
        coerce(x);
        return 0;
}

This yields the output:

x = bffff9f0, &x = bffff9f0, *(void **)&x = 1
x = bffff9f0, &x = bffff9e0, *(void **)&x = bffff9f0

As you can see, taking the address of an array gives the address of its
first element, but taking the address of a pointer gives the address of
the pointer itself. When you take the address of a va_list array that is
coerced to a pointer, it does not yield the same result as when you take
the address of a va_list array that is not coerced. The compiler warns you
about this on platforms where va_list is an array.

> *Sigh* the C vararg stuff
> is awful.

It certainly is.

Reply via email to