Раніше я зручніше використовував спілки; сьогодні я насторожився, коли прочитав цей пост і дізнався, що це код
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 і далі) це законно ( завдяки Паскалю Куоку за те, що це підняло ). Однак спроба зробити це все ж може призвести до невизначеної поведінки , якщо прочитане значення виявиться недійсним (так зване "представлення пастки") для типу, через який він читається. В іншому випадку значення читання визначається реалізацією.
C89 / 90 назвав це не визначеним поведінкою (додаток J), а книга K&R говорить, що його реалізація визначена. Цитата від K&R:
Це мета об'єднання - єдиної змінної, яка може законно містити будь-який з декількох типів. [...] до тих пір, поки використання буде послідовним: отриманий тип повинен бути типом, який останнім часом зберігається. Відповідальність програміста слідкує, який тип зберігається в союзі; результати залежать від реалізації, якщо щось зберігається як один тип і витягується як інший.
Витяг з Stroustrup's TC ++ 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
не може бути суміжним, і, таким чином, не відповідати макеті auint32_t
. Це додатково до питань Ендіанес, на які вказували інші.