3 ms·
Pedantic me thinks p1 = NaN
by flamedoge 9y ago
Pedantic me thinks p1 = NaN
- majewsky 9y agoThat would be undefined as per the last sentence in the quote above, "If the value of the integral part cannot be represented by the integer type, the behavior is undefined." Same goes if p1 = 256.0 and your char type can store 0..255 only, although it would probably be easier to make educated guesses about the result in this case.
- pascal_cuoq 9y agoI would advise against making educated guesses about the result of overflow in the conversion from floating-point to integer: http://blog.frama-c.com/index.php?post/2013/10/09/Overflow-float-integer http://blog.frama-c.com/index.php?post/2013/10/09/Overflow-f... Note: the optimization “Missed simplification of multiplication by integer-valued floating-point constant”, that the article points out that Clang does, relies on this kind of overflow to be undefined and causes yet more unpredictable results in some contexts. If you expect the “a *= 10.0;” statement to be translated to a float-to-int conversion instruction, you may expect the behavior of that instruction to apply on overflow, but it won't because the instruction won't have been generated at all.
- dbaupp 9y agoThat case is undefined but the cast itself isn't, just certain executions of it. If the code never calls the function with bad values, there's no UB, just like how pretty much all cases of UB in C are only undefined for certain values.
- gergo_barany 9y agoHi everyone. I'm the author of the featured post; thanks for the interest. > If the code never calls the function with bad values, there's no UB Exactly. Even if a function might have undefined behavior for some input values, compilers are still required to compile the code correctly for the other input values (if any). And I would still expect them to optimize for those other input values. Anyway, would everyone be happily convinced if I updated the example as follows? #include <math.h> #include <limits.h> char fn1(float p1) { if (isfinite(p1) && CHAR_MIN <= p1 && p1 <= CHAR_MAX) { return (char) p1; } return 0; } I think that covers all that could possibly go wrong. And (unsurprisingly, to me at least) it still shows the same behavior with GCC of storing to the stack and reloading instead of zero-extending register-to-register.