iphone: floats cast to unsigned ints get set to 0 if they are negative?
Asked Answered
S

4

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?

Sholem answered 22/3, 2010 at 7:40 Comment(3)
@KennyTM: some random attempt to stop it optimizing stuff out.Sholem
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.Escalate
Does this answer your question? Is the behaviour of casting a negative double to unsigned int defined in the C standard?Antilles
G
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.

Gascony answered 22/3, 2010 at 8:13 Comment(4)
so why is it not a problem with VC++ or the PSP compiler ?Sholem
@matt: because you're relying on undefined behaviourGascony
@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.Euterpe
@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.Halfhour
A
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.

Asphodel answered 22/3, 2010 at 19:40 Comment(0)
H
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.

Halfhour answered 10/5, 2012 at 20:51 Comment(0)
P
-1

Cast via a signed int.

Polypary answered 22/3, 2010 at 8:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.