Этот союз нарушает строгий псевдоним? Как насчет регистров с плавающей запятой

union
{
Uint32 Integer;
Float32 Real;
} Field;

Я должен использовать этот союз для небольшого трюка IEEE, это нарушает строгий псевдоним? GCC не выдает никаких предупреждений (пробовал с GCC 4.5 и 4.6 даже с педантичным строгим алиасом, но, насколько я знаю, GCC не очень хорошо ловит строгие нарушения правил алиасинга (много ложных срабатываний / негативов).

Field A;
A.Integer = (Value1 & B) || Value2;
return A.Real;

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

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

Приведенный выше код не предназначен для оптимизации, поэтому просто не унижайте меня за злоупотребление оптимизацией, приведенный выше код был для меня самым простым способом получения определенного результата (и, к счастью, самый простой способ, кажется, самый быстрый в мой случай!), если результат не может быть безопасным, то я буду использовать более медленный путь.

заранее спасибо

2

Решение

Псевдоним через объединение определен в C, но имеет неопределенное поведение в C ++; неопределенное поведение эквивалентно тому, что происходит при чтении из неинициализированной переменной (преобразование из lvalue в rvalue).

Соответственно, наиболее вероятный способ, которым это может сломаться, заключается в том, что оптимизатор решит исключить чтение из объединения, поскольку оно не имеет определенного значения. Тем не менее, большинство компиляторов C-and-C ++, скорее всего, дадут вам поведение C, так как они все равно должны его поддерживать.

Безопасный способ присвоения псевдонимов значениям — это побайтное копирование, например. std::memcpy или же std::copy(reinterpret_cast<char *>(...), ...), В качестве альтернативы, если вы можете скомпилировать свой проект как на C, так и на C ++, вы можете переместить код псевдонима объединения в исходный файл C и скомпилировать только этот код как C.

1

Другие решения

Это UB (но не требует строгого алиасинга). Также, unionДанные всегда сохраняются в памяти реализациями AFAIK, иначе потребуется знать, из какого регистра поступили исходные данные, что означает знание типа источника.

0

По вопросам рекламы [email protected]