cstructcastingmemory-layout

Are C-structs with the same members types guaranteed to have the same layout in memory?


Essentially, if I have

typedef struct {
    int x;
    int y;
} A;

typedef struct {
    int h;
    int k;
} B;

and I have A a, does the C standard guarantee that ((B*)&a)->k is the same as a.y?


Solution

  • Are C-structs with the same members types guaranteed to have the same layout in memory?

    Almost yes. Close enough for me.

    From n1516, Section 6.5.2.3, paragraph 6:

    ... if a union contains several structures that share a common initial sequence ..., and if the union object currently contains one of these structures, it is permitted to inspect the common initial part of any of them anywhere that a declaration of the completed type of the union is visible. Two structures share a common initial sequence if corresponding members have compatible types (and, for bit-fields, the same widths) for a sequence of one or more initial members.

    This means that if you have the following code:

    struct a {
        int x;
        int y;
    };
    
    struct b {
        int h;
        int k;
    };
    
    union {
        struct a a;
        struct b b;
    } u;
    

    If you assign to u.a, the standard says that you can read the corresponding values from u.b. It stretches the bounds of plausibility to suggest that struct a and struct b can have different layout, given this requirement. Such a system would be pathological in the extreme.

    Remember that the standard also guarantees that:

    However, and this is important!

    You rephrased the question,

    does the C standard guarantee that ((B*)&a)->k is the same as a.y?

    No! And it very explicitly states that they are not the same!

    struct a { int x; };
    struct b { int x; };
    int test(int value)
    {
        struct a a;
        a.x = value;
        return ((struct b *) &a)->x;
    }
    

    This is an aliasing violation.