Search code examples
cc89

Do fields in identical field sequences have the same offset?


If the first k fields of record type T1 and T2 are identical, are these fields guaranteed to have the same offset? For instance, is this program well-defined?

typedef struct {
    int x, y;
} Shape;

typedef struct {
    int x, y;
    int w, h;
} Rectangle;

static void InitShape(Shape *s)
{
    s->x = 0;
    s->y = 0;
}

int main(void)
{
    Rectangle r;

    InitShape((Shape *) &r);
    r.w = 1;
    r.h = 1;
    return 0;
}

Edit: In my project the C code is generated and including the individual fields from Shape in Rectangle (instead of a single field base of type Shape) simplifies the code elsewhere.


Solution

  • The program is not defined.

    C standard only guarantees that there shall be no padding before the first member of the struct. This means that there may be different amount of padding between members x and y of structs Shape and Rectangle, and when one object of type Rectangle is reinterpreted as type Shape, it might not have the members at the same offsets.

    This is not the main problem as it is reasonable to expect that both members will have the same offsets, and this can be enforced using static asserts.

    The main problem is strict aliasing. There are conditions under which the types may alias1, but those two types don't satisfy any of them. The types Rectangle and Shape are not compatible, and the type Rectangle does not contain a member of type Shape.

    Thus reinterpreting the type Rectangle as the type Shape: InitShape((Shape *) &r);, causes undefined behavior.


    1 6.5 Expressions 7
    An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
    — a type compatible with the effective type of the object,
    — an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union)