Я раньше использовал союзы с комфортом; Сегодня я был встревожен, когда я прочитал этот пост и узнал, что этот код
union ARGB
{
uint32_t colour;
struct componentsTag
{
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
} components;
} pixel;
pixel.colour = 0xff040201; // ARGB::colour is the active member from now on
// somewhere down the line, without any edit to pixel
if(pixel.components.a) // accessing the non-active member ARGB::components
фактически является неопределенным поведением, т. е. чтение из члена объединения, отличного от недавно записанного, приводит к неопределенному поведению. Если это не предполагаемое использование союзов, что это? Кто-нибудь может объяснить это подробно?
Обновить:
Я хотел бы уточнить несколько вещей в ретроспективе.
- Ответ на вопрос не одинаков для C и C ++; моя неосведомленная младшая личность пометила его как C и C ++.
- После изучения стандарта C ++ 11 я не мог окончательно сказать, что он призывает к доступу / проверке неактивного члена объединения не определено / не определено / определяется реализацией. Все, что я мог найти, было §9.5 / 1:
Если объединение стандартной компоновки содержит несколько структур стандартной компоновки, которые имеют общую начальную последовательность, и если объект этого типа объединения стандартной компоновки содержит одну из структур стандартной компоновки, разрешается проверять общую начальную последовательность любой членов структуры стандартного макета. §9.2 / 19: Две структуры стандартного макета разделяют общую начальную последовательность, если соответствующие элементы имеют типы, совместимые с макетом, и ни один из элементов не является битовым полем, либо оба являются битовыми полями с одинаковой шириной для последовательности из одного или более начальных члены.
- В то время как в C ( C99 TC3 - DR 283 и далее) это допустимо ( спасибо Паскалю Куоку за то, что поднял этот вопрос). Однако попытка сделать это может привести к неопределенному поведению , если прочитанное значение окажется недопустимым (так называемое «представление ловушки») для типа, через которое оно читается. В противном случае значение read определяется реализацией.
В C89 / 90 это объясняется неопределенным поведением (Приложение J), а в книге K & R говорится, что реализация определена. Цитата из K & R:
Это цель объединения - единственная переменная, которая может на законных основаниях содержать любой из нескольких типов. [...], пока использование является последовательным: извлеченный тип должен быть последним сохраненным типом. Программист обязан следить за тем, какой тип в данный момент хранится в объединении; результаты зависят от реализации, если что-то хранится как один тип и извлекается как другой.
Выписка из ТС ++ PL Страуструпа (выделено мое)
Использование союзов может иметь важное значение для совместимости данных, [...] иногда неправильно используемых для «преобразования типов ».
Прежде всего, этот вопрос (название которого остается неизменным со времени моего запроса) был задан с намерением понять цель объединения, а не то, что стандарт позволяет, например, Использование наследования для повторного использования кода, конечно, разрешено стандартом C ++, но это не было целью или первоначальным намерением ввести наследование как особенность языка C ++ . По этой причине ответ Андрея продолжает оставаться принятым.
scouring C++11's standard I couldn't conclusively say that it calls out accessing/inspecting a non-active union member is undefined [...] All I could find was §9.5/1
...действительно? Вы цитируете примечание об исключении , а не главное в самом начале абзаца : «В объединении не более одного элемента не статических данных может быть активным в любое время, то есть значение не более одного из Нестатические члены данных могут быть сохранены в объединении в любое время. " - и вплоть до p4: «В общем, нужно использовать явные вызовы деструктора и размещение новых операторов для изменения активного члена объединения »
b, g, r,
иa
может не быть смежным, и, следовательно, не соответствовать макетуuint32_t
. Это в дополнение к проблемам Endianess, на которые указывали другие.