I have read that if you declare two structs like this:
struct Node {
int a, b, c;
};
struct DerivedNode {
struct Node base;
int d, e, f;
};
Then you can use pointers to them like this:
struct DerivedNode myDerivedNode;
struct Node *regularNode = (struct Node *) &myDerivedNode;
regularNode->a = 3;
In other words, the address offsets for a, b, c
are the same within struct Node
and struct DerivedNode
. So you can get a kind of polymorphism out of it, where you can pass in a forcibly (struct Node *)
-cast DerivedNode pointer wherever a Node pointer would normally be taken.
My question is whether this behavior is guaranteed. I know there are some weird memory alignment issues and that the compiler sometimes reorders fields to achieve better packing in memory. Will the base
field ever be located anywhere but the beginning of struct DerivedNode
?
This is guaranteed to work by the standard. Members in structs are layed out sequentially in the order you specify and the first member always appears at offset 0.
Relevant excerpts from the ANSI C standard:
This states that the members are laid out sequentially.
The means that the first member is placed at offset 0.
Note: Standard excerpts taken from section 6.7.2.1 of ISO/IEC 9899:TC3 September 2007 draft.
As David states this is guaranteed as long as
base
remains the first element inDerivedNode
.But generally this is bad practice. I can't figure out much circumstances where you can't say
which is much clearer and less error prone in case you modify your structures later on.
This won't answer your question, but one who cares to write standard ANSI (ISO) C could compile his code with
gcc -pedantic
or-pedantic-errors
. Those options should raise compiling warnings/errors on non-standard lines of code.Note that this is not 100% effective, from
man gcc
: