Yet another ALIGN idea. (some

rbutterworth%watmath.waterloo.edu at CSNET-RELAY.ARPA rbutterworth%watmath.waterloo.edu at CSNET-RELAY.ARPA
Mon Jul 14 23:39:19 AEST 1986


>  From seismo!BRL.ARPA!gwyn  Sat Jul 12 05:07:56 1986
>  You say that an alignof(type) operator is required in order to
>  implement the va_arg(ap,type) macro.  Could you please demonstrate
>  this?  I don't believe it.

Suppose we have a machine where
sizeof(double)==8,  sizeof(long)=8,  sizeof(int)==4,
alignof(double)==8, alignof(long)=4  alignof(int)==4.

What does the macro va_arg(list,long) expand to?
The token "long" can't be concatenated to form a predefined token
such as "align_long" since it could just as easily have been "char *".
So the only information we can really determine about the argument 
is by using sizeof(long).  But this is simply 4 in this case.  We
still don't know where on the stack the argument will be.  If it is
a long (which we can't determine) it is at the next 4-byte boundary,
but if it is a double (which it could just as easily be, given only
its size) it is at the next 8-byte boundary.

How is va_arg supposed to differentiate between these two cases?
I didn't see anything in the standard restricting how things must
be passed in the stack (e.g. all arguments must be aligned the same
way (as in VAX BSD)).  If there isn't an alignof() operator, some
other built-in would be needed (e.g. newptr=align(oldptr,type)).

Another example would be the case of structures.  There is nothing
that says that "struct{char a; char b;}" has to be aligned the same
as "struct{double c;}", and I certainly don't see any way of making
va_arg determine the alignment without a built-in alignof() operator.

With a very strict reading of the standard one might decide that
the "..." arguments can only be of type int, unsigned int, or double.
That would certainly make my above examples invalid, but it would
also make <stdarg.h> much less useful.  If so, the standard could
make this much clearer by changing
    The parameter _^Ht_^Hy_^Hp_^He is a type name such that the type
    of a pointer to an object that has the specified type can be
    obtained simply by postfixing a * to the type name.
to
    The parameter _^Ht_^Hy_^Hp_^He must be "int", "unsigned int"
    or "double".
or better yet, by replacing va_arg by three macros, va_int, va_unsigned,
and va_double.  I really don't think this was what was intended though.



More information about the Comp.lang.c mailing list