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.