
John Maddock wrote:
2) I'm a little surprised at seeing memcpy used to shift 4 bytes, given the slightly-hairy nature of what you're doing here, I don't think a reinterpret_cast to uint32 is unreasonable in comparison. But that's just my opinion :-)
Here's little tip about that. Some compilers (GCC 3.x, for example) don't perform dataflow analysis between certain pairs of types. Therefore, reading the bits of a float as an unsigned int by a construct like: unsigned int x_bits = *reinterpret_cast< unsigned int * >( &x ) (or the reverse) may not generate all of the proper data dependencies. What's really pernicious about this is that because the bug is scheduling-dependent, inline functions which use these constructs may only fail in some cases. The reason compilers do this is because always making conservative decisions about aliasing yields slow code (lots of extra loads & stores). Because certain classes of aliasing are extremely rare (such as the same memory being accessed through both an int * and float *), such cases are excluded from alias analysis. In the case of GCC 3.x, it seems unions avoid this problem. You can also use __attribute__((__may_alias__)). Here's what I used, in my optimized floating-point operations: #define MAY_ALIAS __attribute__ ((may_alias)) typedef unsigned int uint32; typedef uint32 MAY_ALIAS FloatBits; //! Returns the binary representation of a single-precision float as a uint32. inline FloatBits Float_GetBits( const float *p_f //!< Address of value to return. ) { return *reinterpret_cast< const FloatBits * >( p_f ); } Yes, I learned all of this the hard way. ...and was that ever a fun bug to track down! The odd thing is that the error seemed to be not only context-dependent, but also non-deterministic (perhaps based on the value of a not-yet-written memory location?)! :-/ References: http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Type-Attributes.html http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Optimize-Options.html#Optimize-O... Matt Gruenke