Объединение и битовая маскировка, как это работает?

вот некоторый код C:

float phaseFrac(unsigned int inPhase)
{
    union { unsigned int itemp; float ftemp; } u;
    u.itemp = 0x3F800000 | (0x007FFF80 & ((inPhase)<<7));
    return u.ftemp - 1.f;
}

Я не могу обдумать использование здесь «союза». Прав ли я, думая, что, поскольку и uint, и float являются 32-битными, результирующий битовый шаблон в объединении интерпретируется как значение с плавающей запятой? Или здесь есть какая-то другая магия?

Спасибо...


person Giselle    schedule 03.02.2011    source источник


Ответы (4)


arrow_upward
3
arrow_downward

Да, это правильно. Объединение похоже на структуру, за исключением того, что все элементы данных имеют перекрывающееся хранилище, поэтому, если вы записываете поле одного типа, а затем считываете поле какого-либо другого типа, биты первого типа будут переинтерпретированы как значение второго типа. тип.

Код здесь выглядит странно, потому что объединение определяется внутри функции. Обычно объединение объявляется в области файла так же, как объявляется структура, но здесь, поскольку целью является изменение битов, а не хранение данных, это делается локально.

person templatetypedef    schedule 03.02.2011

arrow_upward
1
arrow_downward

Технически это вызывает неопределенное поведение: доступ к члену объединения, отличному от того, который был изменен последним. Однако большинство компиляторов C будут делать то, что вы предполагаете, и интерпретировать битовый шаблон как число с плавающей запятой, и в наши дни почти все используют формат с плавающей запятой IEEE.

person wnoise    schedule 03.02.2011

arrow_upward
0
arrow_downward

Нет, ты прав. float и int - 32 бита. Я предполагаю, что если вы попытаетесь присвоить 0x3F800000 веществу с плавающей запятой, это будет похоже на назначение 1065353216, которое имеет совершенно другую битовую конфигурацию, сохраненную как число с плавающей запятой, что объясняет, почему необходимо целое число.

Число с плавающей запятой необходимо для получения определенного эффекта вычитания 1, который вы не получили бы вычитанием 1 из int по той же причине.

person Neil    schedule 03.02.2011
comment
AFAICR, int не обязательно будет 32-битным или гарантированно будет любой другой конкретной битовой длины. Хотя float, вероятно, будет иметь фиксированную длину в битах. Ах, чудеса С. - person user; 03.02.2011
comment
Верно, и, на мой взгляд, по этой причине этот метод был плохо закодирован. Вместо этого должен был быть массив из 4 байтов. - person Neil; 03.02.2011

arrow_upward
0
arrow_downward

Это должно оказаться полезным на примере, аналогичном вашему вопросу:

http://courses.missouristate.edu/KenVollmar/publications/CCSCWeb.doc

person fR0DDY    schedule 03.02.2011