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?

3
  • @KennyTM: some random attempt to stop it optimizing stuff out.
    – matt
    Mar 22, 2010 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. Jun 4, 2016 at 4:29

4 Answers 4

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.

4
  • so why is it not a problem with VC++ or the PSP compiler ?
    – matt
    Mar 22, 2010 at 8:26
  • 5
    @matt: because you're relying on undefined behaviour
    – Paul R
    Mar 22, 2010 at 8: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, 2010 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. May 10, 2012 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.

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.

-1

Cast via a signed int.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.