3 ms·
How is that undefined behavior? The C spec says: (6.3.1.4) > When a finite value of real floating type is converted to an integer type other than _Bool, the f
by comex 9y ago
How is that undefined behavior? The C spec says: (6.3.1.4)
> When a finite value of real floating type is converted to an integer type other than _Bool, the fractional part is discarded (i.e., the value is truncated toward zero). If the value of the integral part cannot be represented by the integer type, the behavior is undefined.
char is an integer type and float is a real floating type, so the function should be well-defined for at least some input values, although the exact range (including whether or not it includes negatives, i.e. whether plain ‘char’ is signed) is implementation-defined.
- flamedoge 9y agoPedantic 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.