Comment

Comment by OskarS

So the problem here is that in this line:

      if( value < (double) LONG_MIN || value > (double) LONG_MAX)
          return( 0);
The cast of LONG_MAX to double rounds upwards (which is allowed by the standard, which says that rounding direction is "implementation defined"), so that "value > (double) LONG_MAX" is false, right? Even though the mathematical value of "value" is larger than LONG_MAX?

Which then leads to this line:

   l_val = (long) value;
Where value is cast to a long despite being outside of the range of longs, thus causing undefined behavior. So to be clear, BOTH of the -O0 and -O3 versions are correct, since both invoke undefined behaviour.

When -O0 and -O3 give different results, either at least one of them is incorrect and you've stumbled on a compiler bug, or both of them are correct and you're invoking UB (the far more common situation).

EDIT: no, I think I misunderstood it: it's not that value is larger than (double) LONG_MAX, it IS (double)LONG_MAX, so of course "value > (double)LONG_MAX" is false.

The problem is that the "(long)((double)LONG_MAX))" is undefined behaviour on implementations that round (double)LONG_MAX upwards instead of downwards. Which is allowed by the standard. Ok, cool :)

parent OskarS 6 years ago

Discussion

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton