10

try it out:

volatile float bob = -344.0f;
unsigned int fred = (unsigned int)bob;

printf("%d\n",fred);

output will be 0.

obviously I am expecting it to wrap around just as if I had cast from a signed int to an unsgined int (which does wrap and act as expected on the iphone)

we assume it is something to do with the floating point settings.

any ideas?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
matt
  • 4,042
  • 5
  • 32
  • 50
  • @KennyTM: some random attempt to stop it optimizing stuff out. – matt Mar 22 '10 at 12:23
  • old thread, but i've bumped into some more details around this recently. With XCode 7.2.x, casting a negative float to an unsigned short resulted in a wrapped-around value on all iOS platforms tested. however, with XCode 7.3.1, the same code results in truncation to zero on iPad 3 and wrap-around on iPhone 6. – orion elenzil Jun 04 '16 at 04:29
  • Does this answer your question? [Is the behaviour of casting a negative double to unsigned int defined in the C standard?](https://stackoverflow.com/questions/10541200/is-the-behaviour-of-casting-a-negative-double-to-unsigned-int-defined-in-the-c-s) – Peter Cordes Mar 30 '20 at 10:12

4 Answers4

13

This is to be expected - casting a negative float to an unsigned int results in undefined behaviour (UB). If you want the value to wraparound (which is also UB, BTW), then you would need to cast to a (signed) int first and then to unsigned int. Ideally you should not rely on UB at all and find a better way of doing what you need to do.

Paul R
  • 208,748
  • 37
  • 389
  • 560
  • so why is it not a problem with VC++ or the PSP compiler ? – matt Mar 22 '10 at 08:26
  • 5
    @matt: because you're relying on undefined behaviour – Paul R Mar 22 '10 at 08:35
  • 3
    @matt: It *is* a problem on those compilers if you're expecting the int to be 0, which is just as reasonable as expecting it to wrap around. That's the problem with undefined behavior: You can't reasonably expect any particular thing to happen. It could wrap around, it could go to 0, it could send suggestive emails to your employer — it's completely undefined what it will do. – Chuck Mar 22 '10 at 19:44
  • 3
    @matt, just because there is an intuitive result does not mean the behavior is defined by the standard. In particular, the "obvious" conversion is actually quite different than the conversion from the same value in a signed integral type, so one can certainly see why an implementation might prefer to return 0 rather than an unportable and potentially confusing result. Either way, it would be reasonable and conforming, but one way, it's also inconsistent rather than simply unimplemented. – DigitalRoss May 10 '12 at 20:57
4

§6.3.1.4 of the C standard:

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.

So like Paul R said, this is undefined behavior.

Stephen Canon
  • 103,815
  • 19
  • 183
  • 269
0

This conversion is undefined and therefore not portable.

According to C99 §6.3.1.4 footnote 50:

The remaindering operation performed when a value of integer type is converted to unsigned type need not be performed when a value of real floating type is converted to unsigned type. Thus, the range of portable real floating values is (−1, Utype_MAX+1).

And given that this conversion is known not to be portable, it's quite a reasonable interpretation to return 0 rather than a random particular conversion. There are at least two reasons for this: (1) to flag non-portable code rather than propagate it, and (2) just dropping the sign is wildly different from what happens when the same value of an integral type is converted, so it's unclear that any particular alternative is a better idea.

DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
-1

Cast via a signed int.

Andy J Buchanan
  • 1,952
  • 14
  • 13