Я скомпилировал это в gcc и g++ с педантичным, и я не получаю предупреждение ни в одном:
#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;
}
Является ли это законным для C и С++? Я читал о том, как писать, но я не понимаю. Является ли foo(&c.u.b)
отличным от foo((struct b *)&c.u.a)
? Разве они не были бы точно такими же? Это исключение для структур в объединении (от C89 в 3.3.2.3) говорит:
Если объединение содержит несколько структур, которые имеют общий начальный последовательности, и если объект объединения в настоящее время содержит один из этих структур, разрешено проверять общую начальную часть любого из них. Две структуры имеют общую начальную последовательность, если соответствующие члены имеют совместимые типы для последовательности одного или более начальных членов.
В объединении первый член struct a
равен struct a *next
, а первый член struct b
равен struct b *next
. Как вы видите, указатель на struct a *next
записывается, а затем в foo читается указатель на struct b *next
. Являются ли они совместимыми типами? Они оба указывают на структуру, и указатели на любую структуру должны быть одного размера, поэтому они должны быть совместимыми, а макет должен быть таким же правильным? Можно ли читать i
из одной структуры и писать в другую? Могу ли я совершать какие-либо нарушения псевдонимов или нарушения типа?