Союз и немного маскировки, как это работает? - PullRequest
1 голос
/ 03 февраля 2011

вот код 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-битными, результирующий битовый шаблон в объединении интерпретируется как значение с плавающей точкой? Или здесь какая-то другая магия?

Спасибо ...

Ответы [ 4 ]

3 голосов
/ 03 февраля 2011

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

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

1 голос
/ 03 февраля 2011

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

0 голосов
/ 03 февраля 2011

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

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

0 голосов
/ 03 февраля 2011

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

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

...