2010-03-22 5 views
7

Pruébelo:iphone: los flotantes lanzados a ints sin firmar se establecen en 0 si son negativos?

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

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

salida será 0.

, obviamente, estoy esperando que se ajuste alrededor como si yo hubiera desechado de una int firmado a un int unsgined (que envuelva y actuar como se esperaba en el iphone)

asumimos que tiene algo que ver con la configuración del punto flotante.

¿Alguna idea?

+2

'volátil'? o_O – kennytm

+0

@KennyTM: algún intento aleatorio para detenerlo optimizando cosas. – matt

+0

hilo antiguo, pero me he topado con algunos detalles más sobre esto recientemente. Con XCode 7.2.x, lanzar un float negativo a un short sin signo resultó en un valor envolvente en todas las plataformas iOS probadas. sin embargo, con XCode 7.3.1, el mismo código da como resultado el truncamiento a cero en el iPad 3 y el wrap-around en el iPhone 6. –

Respuesta

11

Esto es de esperarse: emitir un flotante negativo a un int sin signo da como resultado un comportamiento indefinido (UB). Si desea que el valor sea envolvente (que también es UB, BTW), entonces deberá convertir primero a (firmado) int y luego a unsigned int. Lo ideal es que no confíe en UB en absoluto y encuentre una mejor manera de hacer lo que necesita hacer.

+0

entonces ¿por qué no es un problema con VC++ o el compilador de PSP? – matt

+4

@matt: porque confía en un comportamiento indefinido –

+2

@matt: It * is * es un problema en esos compiladores si espera que int sea 0, lo que es tan razonable como esperar que se complete.Ese es el problema del comportamiento indefinido: no se puede esperar razonablemente que ocurra algo en particular. Podría cambiar, podría ir a 0, podría enviar correos electrónicos sugestivos a su empleador, no está completamente definido lo que hará. – Chuck

0

Emitir a través de un int firmado.

4

§6.3.1.4 de la norma C:

Cuando un valor finito de bienes tipo flotante se convierte en un tipo entero distinto _Bool, la parte fraccionaria se descarta (es decir, el valor es truncado hacia cero). Si el valor de la parte integral no puede ser representado por el tipo entero, el comportamiento no está definido.

Así como Paul R dijo, esto no es comportamiento definido.

0

Esta conversión no está definida y, por lo tanto, no es portátil.

Según C99 §6.3.1.4 nota 50:

La operación en Saldo lleva a cabo cuando un valor de tipo entero se convierte en tipo sin signo no debe efectuarse cuando un valor de tipo flotante verdadero se convierte a unsigned tipo. Por lo tanto, el rango de valores flotantes reales portátiles es (-1, Utype_MAX + 1).

Y dado que se sabe que esta conversión no es portátil, es una interpretación bastante razonable devolver 0 en lugar de una conversión en particular al azar. Hay al menos dos razones para esto: (1) marcar el código no portátil en lugar de propagarlo, y (2) simplemente soltar el signo es muy diferente de lo que sucede cuando se convierte el mismo valor de un tipo integral, por lo que es no está claro que una alternativa en particular sea una mejor idea.

Cuestiones relacionadas