Стандарт ISO C, необходимый для работы, является следующей ситуацией:
union U {
struct X x;
struct Y y;
struct Z z;
/* ... */
};
Если структуры разделяют некоторую общую начальную последовательность элементов, то к этой начальной последовательности можно получить доступ через любого из элементов. , Например:
struct X {
/* common members, same as in Y and Z: */
int type;
unsigned flags;
/* different members */
};
Если все структуры имеют type
и flags
в одном и том же порядке и одинаковых типов, то это необходимо для работы:
union U u;
u.x.type = 42; /* store through x.type */
foo(u.y.type); /* access through y.type */
Другие хаки этого типа не «благословлены» ISO C.
Ситуация там немного другая. Вопрос в том, можем ли мы, если у ведущего элемента структуры, преобразовать указатель на структуру в тип этого члена, а затем использовать его. Простейший случай выглядит примерно так:
struct S {
int m;
};
Учитывая объект struct S s
, мы можем взять адрес m
, используя &s.m
, получив указатель int *
. Эквивалентно, мы можем получить тот же указатель, используя (int *) &s
.
ISO C требует, чтобы структура имела тот же адрес, что и ее первый член; указатель на структуру и указатель на первый член имеют другой тип, но указывают на один и тот же адрес, и мы можем преобразовать их между собой.
Это не ограничено уровнями вложенности. Учитывая a
этого типа:
struct A {
struct B {
struct C {
int m;
} c;
} b
};
адрес &a.b.c.m
остается таким же, как адрес &a
. Указатель &a.b.c.m
совпадает с (int *) &a
.