I've compiled this in gcc and g++ with pedantic and I don't get a warning in either one:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct a {
struct a *next;
int i;
};
struct b {
struct b *next;
int i;
};
struct c {
int x, x2, x3;
union {
struct a a;
struct b b;
} u;
};
void foo(struct b *bar) {
bar->next->i = 9;
return;
}
int main(int argc, char *argv[]) {
struct c c;
memset(&c, 0, sizeof c);
c.u.a.next = (struct a *)calloc(1, sizeof(struct a));
foo(&c.u.b);
printf("%d\n", c.u.a.next->i);
return 0;
}
Is this legal to do in C and C++? I've read about the type-punning but I don't understand. Is foo(&c.u.b)
any different from foo((struct b *)&c.u.a)
? Wouldn't they be exactly the same? This exception for structs in a union (from C89 in 3.3.2.3) says:
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. Two structures share a common initial sequence if corresponding members have compatible types for a sequence of one or more initial members.
In the union the first member of struct a
is struct a *next
, and the first member of struct b
is struct b *next
. As you can see a pointer to struct a *next
is written, and then in foo a pointer to struct b *next
is read. Are they compatible types? They're both pointers to a struct and pointers to any struct should be the same size, so they should be compatible and the layout should be the same right? Is it ok to read i
from one struct and write to the other? Am I committing any type of aliasing or type-punning violation?
struct a
is compatible withstruct b
. – Slovak