Questa è l'implementazione radice quadrata veloce inversa da Quake III Arena:Il cast del puntatore interrompe la regola di aliasing rigorosa?
float Q_rsqrt(float number)
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * (long *) &y; // evil floating point bit level hacking
i = 0x5f3759df - (i >> 1); // what?
y = * (float *) &i;
y = y * (threehalfs - (x2 * y * y)); // 1st iteration
// y = y * (threehalfs - (x2 * y * y)); // 2nd iteration, this can be removed
return y;
}
ho notato che long inti
assume il valore Dereferenced all'indirizzo (cast a un long *
) di galleggiantey
. Il codice esegue quindi le operazioni su i
prima di memorizzare il valore di riferimento sull'indirizzo (assegnato a float *
) di i
in .
Questo interromperà la rigida regola di aliasing dal i
non è dello stesso tipo di ?
Penso che forse non lo è poiché il valore è dereferenziato e copiato; quindi le operazioni vengono eseguite su una copia anziché sull'originale.
Penso che certianamente lo faccia, almeno finchè 'sizeof (long)! = Sizeof (float)'. –
'sizeof' non ha nulla a che fare con la violazione di aliasing. –
Il codice come scritto assume 'long' è un valore a 32 bit, proprio come un' float'. Il cast del puntatore sembra insidioso, anche se non sono sicuro che sia vietato dal momento che il compilatore può "vedere" cosa sta succedendo [a differenza di uno scenario in cui un puntatore viene memorizzato da qualche parte e poi usato in un modo sorprendente]. Penso che i problemi di aliasing possano essere risolti tramite i cast intervenienti a '(unsigned char *)', senza generazione di codice nei casi che avrebbero funzionato comunque. La mia stessa inclinazione potrebbe essere quella di usare un 'unione' invece. Ancora non è davvero portatile, ma i compilatori dovrebbero aspettarsi che i sindacati siano pseudonimi. – supercat