Gianni said:
True - that did happen. But the C libraries still survived and this is
one of those things that needs to be consistant across C and C++.
Come to think of that, I have a vague recollection that the layout of
members in C requires that they are laid out like this.
There is OODLES of code written in C that depends on this behaviour.
Take the X protocol header files as one example and this is meant to
work between DIFFERENT compilers !
If someone has a C standard handy, please look up the conventions on how
members must be laid out in a struct. If I remember correctly (and it's
been years and I don't remeber the document - it could have been K&R
TCL), members in a struct must be laid out so that the members are
placed in order of declaration. (padding between members to preserve
alignment is compiler specific.)
I think there are struct layout guarentees but I don't have a reference
handy to give a definitive answer.
Some sort of confusion is going on here I think. It was my
understanding that we where talking about comparing an array, which is
guaranteed to be contiguous, to a structure that has no such guarantee.
It is true that they are guarteed to be in order, but there is nothing
that states how far apart they are.
X never, afaik, uses any translation between array and structure. There
are two pieces that I know of where they do something that could be
mistaken for similar, unions such as XEvent, and offsets in Xt. The
XEvent union looks something like this:
typedef union
{
XMouseEvent mouseEvent,
XKeyEvent keyEvent,
...
} XEvent;
And each of the events in that union are a structure that always starts
with "int type". By my understanding this is the only structure element
that is guaranteed to always look the same no matter how you access it,
it has been a long time since I used Xlib. Based on this element you
typecast the XEvent to the particular type that it is and access its
elements from this new casting.
The second is the XOffset (XtOffset?) macro in Xt which looks something
like:
#define XOffset(x, y) ((x*)NULL)->y - (x*)NULL
but there are other definitions because this is apparently not portable.
This is then used to create an OO heigherarchy by incrementally adding
offsets as you dive into the object to get to the particular member in
question.
So, back to the origional:
union {
T c[4];
struct { T c0, c1, c2, c3 };
}
There is nothing that guarantees that &c
== &ci even if it is
commonly the case. I am pretty sure that X would not depend on behavior
like this.
NR