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

вот некоторый код 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)


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

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

person templatetypedef    schedule 03.02.2011

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

person wnoise    schedule 03.02.2011

Нет, ты прав. 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

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

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

person fR0DDY    schedule 03.02.2011