0

Say I have a float I'd like to get the word value of:

float f = 42.0f; // 0xDEADBEEF

There are two options I know of.

  1. Type-pun with
std::cout << *(int*)&f;

This is undefined behavior, and I don't care to use a char* as an exception (as shown here: dereferencing type-punned pointer will break strict-aliasing rules) since floats are 4 bytes and that would be messy.

  1. Use a union
union {
    float f;
    int i;
};

f = 42.0f;
std::cout << i;

This is also undefined behavior last time I checked, although this answer disagrees: What is the strict aliasing rule?

Is my only option to disable strict aliasing? I think there ought to be a way to get the underlying value (I'm computing a check sum if you're curious) without making such a large change.

  • 3
    Consider `memcpy()`. A good compiler will analyze and emit efficient code. – chux - Reinstate Monica Mar 29 '20 at 15:30
  • 1
    *This is undefined behavior, and I don't care to use a `char*` as an exception* If using proper constructs to avoid undefined behavior is something you don't care to do, C and C++ are probably not the tools you should be using. – Andrew Henle Mar 29 '20 at 15:31
  • you suppose _int_ and _float_ have the same size, are you sure of that ? – bruno Mar 29 '20 at 15:37
  • "*I think there ought to be a way to get the underlying value*" There are ways to get the underlying value. But you defined the problem such that all of those ways are something you consider "messy". So you're left with UB. – Nicol Bolas Mar 29 '20 at 15:52
  • @chux memcpy is the clear answer here. Thank you. – MalumProhibitum Mar 29 '20 at 16:03
  • @bruno You are correct, that is not always the case and I should have specified. – MalumProhibitum Mar 29 '20 at 16:04
  • If the hecklers are so confident about their solutions, by all means, provide an example. I don't care to sum word values byte by byte. – MalumProhibitum Mar 29 '20 at 16:07
  • Note that the authors of the Standard stated that when the Standard classifies something as Undefined Behavior, that--among other things--identifies areas of "conforming language extension". The question of whether a compiler can recognize that an expression like `*((uint32_t*)someFloatPtr)` might actually access the storage associated with a `float` is a Quality of Implementation issue, outside the Standard's jurisdiction. – supercat Apr 01 '20 at 19:57
  • @MalumProhibitum: Good username, given the subject of this post. A bizarre myth has taken root that the authors of the Standard intended to prohibit actions classified as Undefined Behavior, despite the fact that they explicitly acknowledge that one of C's strength the ability of many implementations to use non-portable constructs to do things that wouldn't be possible in portable C, and explicitly state that implementations can define the behavior of non-portable constructs in cases where the Standard doesn't. – supercat Apr 01 '20 at 20:03

0 Answers0