Посмотрите на этот код:
struct A {
short s;
int i;
};
struct B {
short s;
int i;
};
union U {
A a;
B b;
};
int fn() {
U u;
u.a.i = 1;
return u.b.i;
}
Гарантируется ли это, что fn()
возвращается 1
?
Примечание: это дополнительный вопрос к этот.
Да, это определенное поведение. Сначала давайте посмотрим, что говорит стандарт о A
а также B
, [Class.prop] / 3 имеет
Класс S является классом стандартной компоновки, если он:
- не имеет нестатических членов-данных типа нестандартного класса макета (или массива таких типов) или ссылки,
- не имеет виртуальных функций и виртуальных базовых классов,
- имеет одинаковый контроль доступа для всех нестатических элементов данных,
- не имеет базовых классов нестандартной компоновки,
- имеет не более одного подобъекта базового класса любого данного типа,
- имеет все нестатические члены-данные и битовые поля в классе и его базовые классы, впервые объявленные в том же классе, и
- […] (ничего не сказано здесь имеет какое-либо отношение в этом случае)
Так A
а также B
оба стандартные типы макетов. Если мы посмотрим на [Class.mem] / 23
Два типа структуры стандартного макета являются классами, совместимыми с макетом, если их общая начальная последовательность включает в себя все члены и битовые поля обоих классов ([basic.types]).
а также [Class.mem] / 22
Общая начальная последовательность двух структурных типов стандартного макета представляет собой самую длинную последовательность нестатических элементов данных и битовых полей в порядке объявления, начиная с первого такого объекта в каждой из структур, так что соответствующие объекты имеют типы, совместимые с макетом. либо оба объекта объявляются с атрибутом no_unique_address ([dcl.attr.nouniqueaddr]), либо ни один из них не является, и либо оба объекта являются битовыми полями с одинаковой шириной, либо ни один не является битовым полем.
а также [Class.mem] / 25
В объединении стандартной компоновки с активным членом типа структуры T1 разрешается считывать нестатический член данных m другого члена объединения типа структуры T2, если m является частью общей начальной последовательности T1 и T2; поведение такое, как если бы соответствующий член T1 был назначен. [ Пример:
struct T1 { int a, b; }; struct T2 { int c; double d; }; union U { T1 t1; T2 t2; }; int f() { U u = { { 1, 2 } }; // active member is t1 return u.t2.c; // OK, as if u.t1.a were nominated }
— конец примера] [Примечание: чтение летучего объекта через glvalue энергонезависимого типа имеет неопределенное поведение ([dcl.type.cv]). — конец примечания]
Тогда мы имеем, что классы имеют одинаковую общую начальную последовательность, выложены одинаково, и доступ к одному и тому же члену неактивного типа рассматривается как доступ к этому члену активного типа.
Других решений пока нет …