logoalt Hacker News

C++ float-to-int conversion can be undefined behavior

38 pointsby signa11last Thursday at 9:59 AM38 commentsview on HN

Comments

digitalPhonixlast Thursday at 6:36 PM

Herb Sutter's comment on why it's ok is confusing to me:

> Regarding the use of UB internally: It's okay and if anyone is worried about it the use of UB is benign on the platforms we target (e.g., they don't involve hitting any hardware trap representations for these types)

Isn't the outcome of the UB (ie. whether it will "rm -rf /" or something else) dependent on both the target and the compiler? And the compiler (or future compiler) could plausibly make the assumption that the narrowing to an unrepresentable value will never occur and change behaviour because of it?

show 6 replies
gpvostoday at 6:49 PM

Sounds like the standard should say that it results in an implementation-defined value (or wording to that effect). Saying it's UB gives the compilers way too much leeway.

show 1 reply
pjmlptoday at 4:57 PM

Hopefully this will be part of UB fixes for C++29, where plenty of UB is being redefined as erroneous behaviour instead.

dmitrygrtoday at 7:18 PM

> The correct fix is to bounds check before casting.

This will do wonders for speed. Actually explicitly using the safe isntr might be better. Something like this will happily compile to a single instr and cause you no grief even if the compiler had it out for you with UB. These instrs all clearly define outputs for all inputs (note that said outputs may not match across architectures)

   static inline __attribute__((always_inline)) int f2i(float myFloat) {
      int myInt;

      #if defined(__arm__)
         asm("VCVT.S32.F32 %0, %1":"=r"(myInt), "t"(myFloat));
      #elif defined (__aarch64__)
         asm("FCVTZS %0, %1":"=r"(myInt), "w"(myFloat));
      #elif defined (__x86_64__)
         asm("CVTTSS2SI %0, %1":"=r"(myInt), "x"(myFloat));
      #else
         #if 0 // be boring
            if (myFloat <= TOO_SMALL_FLOAT || myFloat => TOO_BIG_FLOAT)
               abort();
         #else
            #warning "Embrace the UB"
         #endif
         myInt = (int)myFloat;
      #endif
      return myInt;
   }
orangepandatoday at 5:03 PM

How could it be defined behaviour, when the result is different on ARM and x86?

show 2 replies
lionkorlast Thursday at 3:42 PM

The core guidelines library is definitely not doing the right thing here. Very odd.

functionmousetoday at 7:30 PM

float considered harmful

Byte-Nautlast Thursday at 10:27 AM

[dead]