Is this code guaranteed by the C standard?

I read that if you declare two such structures:

struct Node { int a, b, c; }; struct DerivedNode { struct Node base; int d, e, f; }; 

Then you can use pointers for them as follows:

 struct DerivedNode myDerivedNode; struct Node *regularNode = (struct Node *) &myDerivedNode; regularNode->a = 3; 

In other words, the address offsets for a, b, c same within the struct Node and struct DerivedNode . That way, you can get a kind of polymorphism from where you can force the (struct Node *) -cast pointer to the DerivedNode pointer wherever the Node pointer will normally execute.

My question is whether this behavior is guaranteed. I know that there are some strange problems with memory alignment and that the compiler sometimes reorders fields to achieve better memory packing. Will the base field be anywhere but the start of the struct DerivedNode ?

+7
source share
3 answers

This is guaranteed to work by standard. Members in the structures line up sequentially in that order, and the first member always appears with an offset of 0.

Relevant excerpts from the ANSI C standard:

A structure is a type consisting of a sequence of elements whose storage is distributed in an ordered sequence.

This means that the elements are laid out sequentially.

A structural object may have an unnamed addition, but not at the beginning.

Means means that the first element is placed at offset 0.

Note. Standard extracts from section 6.7.2.1 of the draft ISO / IEC 9899: TC3, September 2007

+13
source

According to David, this is guaranteed as long as base remains the first element in DerivedNode .

But overall this is bad practice. I cannot understand many circumstances when you cannot say

 struct Node *regularNode = &myDerivNode.base; 

which is much clearer and less error prone if you subsequently change your structures.

+3
source

This will not answer your question, but anyone who wants to write standard ANSI (ISO) C can compile their code using gcc -pedantic or -pedantic-errors . These parameters should raise compilation of warnings / errors on non-standard lines of code.

Please note that this is not 100% more efficient from man gcc :

[- pedantic] finds some practices other than ISO, but not all - only those for which ISO C requires diagnostics, and some others for which diagnostics have been added.

+1
source

All Articles