I am going to take the liberty of crossposting this to comp.lang.c++
(originally comp.lang.c), and to summarize the discussion for the sake
of those reading only c++.
The question is: If you are writing C and you have a struct P, can you
create a struct C that is an extension of the first (starts just like P
and adds some data), and then use a C* as if it were an P*?
Example:
typedef struct {
int a;
short b;
} P;
typedef struct {
int a;
short b;
long long c;
} C;
C *c; P *p;
c = (C*) malloc(sizeof(C));
c->a = 1; c->b =2;
p = (P*) c;
printf("%d\n", p->a);
P and C stand for parent and child, and hint at the OO structure that we
are tying to mimick in C. We want to be able to use a child struct as a
parent struct, as you would in C++.
The basic answer in comp.lang.c is "it works on any compiler I have
seen, but there is no guarantee".
The standard appears to limit the freedom of the compiler in laying out
the struct: the order of the elements if fixed, padding can be added
between elements and at the end, but only if necessary for alignment.
This does not quite prescribe where the padding should be. If you have
three byte-aligned bytes, and a 4-byte aligned 4-byte word, you need one
byte of padding, but you can put that whereever you want before the
word: bbbpwwww or bpbbwwww are both allowed (b is a byte, p padding, and
w part of the word). The standard apperently does not require that the
padding is applied the same way in different structs.
Another problem that has been pointed out is this: what if P ends in a
4-byte aligned byte b and 3 bytes of padding. The compiler may decide
that the most efficient way to clear b is to do a four-byte clear
operation. If C adds 3 bytes to the struct, these may go in the
padding, and an attempt to assign p.b=0 may clear the extra the extra
bytes in C if p points to a C struct.
Now the reason to crosspost to comp.lang.c++: I think the c++ to c
translator used overlapping for inheritance, so the c++ people must be
experts. Am I correct? Does that mean that the translator depended on
features of the compilers that are not prescribed by the standard, or am
I missing something?
It is clear that there are alternatives, e.g., we may define C as
typedef struct {
P p;
long c;
} C;
at the expense of some extra typing when accessing common elements.
[disclaimer: I do not have the C standard. Everyting I write about it
is either hearsay or Harbison & Steele.]
Roderick