I have a struct X which inherits from struct Base. However, in my current setup, due to alignment, size of X is 24B:
typedef struct {
double_t a;
int8_t b;
} Base;
typedef struct {
Base base;
int8_t c;
} X;
In order to save the memory, I'd like to unwind the Base struct, so I created struct Y which contains fields from Base (in the same order, always at the beginning of the struct), so the size of the struct is 16B:
typedef struct {
double_t base_a;
int8_t base_b;
int8_t c;
} Y;
Then I'm going to use instance of struct Y in a method which expects a pointer to Base struct:
void print_base(Base* b)
{
printf("%f %d\n", b->a, b->b);
}
// ...
Y data;
print_base((Base*)&data);
Does the code above violates the strict aliasing rule, and causes undefined behavior?
First,
Base
andY
are not compatible types as defined by the standard 6.2.7, all members must match.To access an
Y
through aBase*
without creating a strict aliasing violation,Y
needs to be "an aggregate type" (it is) that contains aBase
type among its members. It does not.So it is a strict aliasing violation and furthermore, since
Y
andBase
are not compatible, they may have different memory layouts. Which is kind of the whole point, you made them different types for that very reason :)What you can do in situations like this, is to use unions with struct members that share a common initial sequence, which is a special allowed case. Example of valid code from C11 6.5.2.3: