Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 291
Soumya Avatar asked Nov 06 '13 05:11

Soumya


1 Answers

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:

  • Structures are never trap representations.

  • Addresses of fields in a structure increase (a.x is always before a.y).

  • The offset of the first field is always zero.

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.

like image 87
Dietrich Epp Avatar answered Oct 29 '22 13:10

Dietrich Epp