Does this union break strict aliasing? What about

2019-02-27 12:30发布

问题:

union
{
    Uint32 Integer;
    Float32 Real;
} Field;    

I have to use that union for a little IEEE trick, does that break strict aliasing? GCC is not throwing any warning(tried with GCC 4.5 and 4.6 even with pedantic strict aliasing, but As Far As I Know, GCC is not very good catching strict aliasing rules infringiments (lots of false positives/negatives).

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

That's the snippet I'm currently using, it seems working correctly without any warning, but maybe there can be side effects or undefined behaviours with certain compilers optimizations. So If that piece of code can be unsafe under certain conditions I will use some effort to remove that.

Also I assume that this piece of code will require moving data from standard registers to floating pointing registers on most modern CPUs (just curious about that), involving some extra cycles respect to older CPUs, correct?

The code above don't intend to be an optimization, so just don't derogate me for abusing optimizing, the code above was the simplest way for me to obtain a certain result (and luckily the simplest way seems also to be the fastest in my case!), if the result can't be safe, then I'll use a slower way.

Thanks in advance

回答1:

Aliasing via a union is defined in C but has undefined behaviour in C++; the undefined behaviour is equivalent to that which occurs when reading from an uninitialized variable (a lvalue-to-rvalue conversion).

Accordingly, the most likely way this would break is in the optimiser deciding to eliminate the read from the union, as it does not have a defined value. However, most C-and-C++ compilers are likely to give you the C behaviour as they need to support that anyway.

The safe way to alias the values is via bytewise copy e.g. std::memcpy or std::copy(reinterpret_cast<char *>(...), ...). Alternatively, if you can compile your project in both C and C++ you could move the union aliasing code to a C source file and compile just that code as C.



回答2:

It is UB (but doesn't require strict aliasing). Also, uniond data is always stored in memory by implementations, AFAIK, else would require knowing which register the source data came from, which means knowing the source type.