1

Copying bit pattern of a float value into a uint32_t or vice versa (not casting them), we can copy bits byte-to-byte using std::copy or memcpy. Another way is to use reinterpret_cast as below (?):

float f = 0.5f;
uint32_t i = *reinterpret_cast<uint32_t*>(&f);

or

uint32_t i;
reinterpret_cast<float&>(i) = 10;

However there is a claim that says two reinterpret_cast used above, invokes undefined behavior. Is that true? How?

masoud
  • 55,379
  • 16
  • 141
  • 208
  • 1
    As stated by the answer it is UB. a assertion that `sizeof(uint32_t) == sizeof(float)` though should be all you need to feel confident that it will work. – NathanOliver Aug 03 '16 at 13:08
  • @NathanOliver But if the compiler does type-based alias optimizations then it could reasonably break the behaviour if you don't supply `-fno-strict-aliasing` or something. – TartanLlama Aug 03 '16 at 14:02
  • @TartanLlama Good point. checking `alignof` might also be needed. – NathanOliver Aug 03 '16 at 14:05
  • Note that there's even discussion as to whether the `memcpy` approach is defined. See [here](http://open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3751.pdf) and [here](http://stackoverflow.com/questions/30114397/constructing-a-trivially-copyable-object-with-memcpy). – TartanLlama Aug 03 '16 at 14:45

1 Answers1

6

Yes, this is undefined behaviour as it breaks the strict aliasing rule:

[basic.lval]/10: If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined — the dynamic type of the object,

— a cv-qualified version of the dynamic type of the object,

— a type similar (as defined in 4.4) to the dynamic type of the object,

— a type that is the signed or unsigned type corresponding to the dynamic type of the object,

— a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,

— an aggregate or union type that includes one of the aforementioned types among its elements or non- static data members (including, recursively, an element or non-static data member of a subaggregate or contained union),

— a type that is a (possibly cv-qualifded) base class type of the dynamic type of the object,

— a char or unsigned char type.

Since uint32_t is none of the above when trying to access an object of type float, the behaviour is undefined.

TartanLlama
  • 63,752
  • 13
  • 157
  • 193