Это быстрая реализация метода вычисления обратного квадратного корня из Quake III Arena:
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;
}
Я заметил, что long int i
принимает разыменованное значение по адресу (преобразованному в long *
) float y
. Затем код выполняет операции с i
перед сохранением разыменованного значения по адресу (приведенному к float *
) i
в y
.
Нарушит ли это правило строгого псевдонима, поскольку i
не того же типа, что и y
?
Я думаю, что, возможно, это не так, поскольку значение разыменовано и скопировано; поэтому операции выполняются с копией, а не с оригиналом.
sizeof(long) != sizeof(float)
. - person   schedule 04.04.2013sizeof
не имеет ничего общего с нарушением псевдонима. - person R.. GitHub STOP HELPING ICE   schedule 04.04.2013long
- 32-битное значение, как иfloat
. Приведение указателя кажется изворотливым, хотя я не уверен, что это запрещено, поскольку компилятор может видеть, что происходит (в отличие от сценария, где указатель где-то хранится, а затем используется неожиданным образом). Я думаю, что проблемы с псевдонимом можно решить с помощью промежуточных преобразований в(unsigned char*)
, без генерации кода в случаях, которые в любом случае сработали бы правильно. Я мог бы использовать вместо этогоunion
. Все еще не совсем переносимый, но компиляторы должны ожидать, что объединение будет псевдонимом. - person supercat   schedule 04.04.2013unsigned char *
не устранит этот недостаток. (Только преобразования указателя без разыменования в некоторой степени определены при условии, что выравнивание совместимо, что определяется реализацией.) - person Eric Postpischil   schedule 04.04.2013