2010-08-13 8 views
4

Не будут ли объединение в this вопроса вызывает UB, когда используются как это:Союзов для извлечения данных

union Data 
{ 
    unsigned int intValue; 
    unsigned char argbBytes[4]; 
}; 
Data data; 
data.intValue = 1235347; 
unsigned char alpha = data.argbBytes[0]; //UB? 

Я думаю о 9.5/1 в стандарте:

В союзе , не более одного из данных членов могут быть активны в любое время, , то есть значение не более одного из элементов данных может быть сохранено в союзе в любое время.

+0

Да, это UB. Но это почти наверняка «работает». – 2010-08-13 08:25:16

+0

Вот что я подумал;) –

ответ

3

В общем, вы правы, записывая значение одного типа в объединение, а затем считывая его как другой тип - это неопределенное поведение. с другой стороны, в стандарте явным образом допускается, чтобы что-либо использовалось как массив символов. он никогда не был на 100% понятен мне, который имеет приоритет, но все реализации, которые я когда-либо использовал, позволяют делать кастинг в любом случае.

+0

Этот трюк профсоюза не квалифицируется как «кастинг», поэтому факт, что все можно преобразовать в 'char []', не имеет значения. Согласно стандарту, использование такого объединения - UB, но настолько распространено, что компиляторы склонны явно гарантировать, что он будет работать. – jalf

+2

@jalf Стандарт никогда явно не говорит, что использование такого объединения - это UB. Таким образом, для меня это выглядит просто как псевдоним, и наложение любого объекта с использованием 'unsigned char' явно разрешено. –

+0

@ Johannes: Хмм, справедливая точка. Я не думаю, что у вас есть ссылка или две удобные в отношении псевдонимов на 'char', которые разрешены? – jalf

3

Я полагаю, что это было бы неопределенным, поскольку то, что вы сделали, зависит от платформы. alpha будет в конечном итоге как другое значение в зависимости от того, является ли ваша платформа большой или маленькой.

Но техника, которую вы показываете, в значительной степени эквивалентна выполнению reinterpret_cast.

Я думаю, что стандарт указывает, что вы не можете хранить разные значения в обоих элементах (поскольку они перекрываются в памяти).

Настоящая причина, по которой профсоюз был изобретен, состоял в том, чтобы позволить людям подбирать больше данных в меньшем объеме памяти. Традиционно, наряду с объединением, вы бы сохранили некоторый маркер (возможно, бит или два, хранящиеся в битовой маске) ​​вне союза, чтобы помнить, какой член союза активен. Используя этот маркер, вы тщательно кодируете обращения к объединению, чтобы вы только читали активный член.

+0

Дело в том, что что-то вроде '(reinterpret_cast (& data.intValue)) [0]' также UB (5.2.10/7). Несмотря на то, что я уверен, что извлечение байта из int через объединение будет работать отлично, я все еще думаю, что это UB. –

+0

стандарт не указывает на то, что вы не можете одновременно иметь обоих членов. проблема в том, что в целом значение одного элемента может не быть конвертируемым в значение другого члена, например. у вас могут быть некоторые бит ловушки –

0

Непонятно из сообщения, что такое размер 'int' на платформе. Предположим, что 32-битный целочисленный и 8-битный символ, т. Е. Sizeof (int) == 4.

Также неясно, что такое конечная машина. Предположим, что маленький конец.

С этой undertanding, 0x12D993 (десятичное 1235347) будет сохранен как

0x93 0xd9 0x12 0x00 (увеличение адрес)

Когда эта память доступна через 'argbBytes', значение argbBytes [0] действительно зависит от конечности машины. Следовательно, это не неопределенное поведение, а поведение, определяемое реализацией.

+1

Неважно, что такое платформа. В стандарте говорится, что это неопределенное поведение, поэтому это UB. Конкретный компилятор может гарантировать, что это работает, но это выходит за рамки стандарта и не может быть использовано для работы на каждом компиляторе/платформе. – KeithB

+0

@KeithB: Пожалуйста, дайте ссылку на стих в Стандарте. – Chubsdad

+0

@chubsdad: неправильный путь вокруг. Это неопределенное поведение, если вы не можете указать на часть стандарта, которая говорит, что это не так. По умолчанию используется UB. ;) – jalf

Смежные вопросы