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
?
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.
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.