这个指针转换是否破坏严格别名规则? [英] Does this pointer casting break strict aliasing rule?
问题描述
这是Quake III Arena的快速平方根实现:
This is the fast inverse square root implementation from 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
使用 float <$ c $的地址处的引用值(转换为 long *
c> y 。然后,代码在将地址(转换为 float *
)存储之前对 i
code> i into y
。
I noticed that long int i
takes the dereferenced value at the address (cast to a long *
) of float y
. The code then performs operations on i
before storing the dereferenced value at the address (cast to a float *
) of i
into y
.
因为 i
与 y
?
我认为也许不会,因为值被取消引用和复制;
I think that perhaps it doesn't since the value is dereferenced and copied; so the operations are performed on a copy rather than the original.
推荐答案
是的,这个代码被严重破坏并调用未定义的行为。特别注意这两行:
Yes, this code is badly broken and invokes undefined behavior. In particular, notice these two lines:
y = number;
i = * ( long * ) &y; // evil floating point bit level hacking
由于对象 * )& y
有类型 long
,编译器可以自由地假定它不能别名为 float
;因此,编译器可以相对于彼此重新排序这两个操作。
Since the object *(long *)&y
has type long
, the compiler is free to assume it cannot alias an object of type float
; thus, the compiler could reorder these two operations with respect to one another.
要修复它,应该使用union。
To fix it, a union should be used.
这篇关于这个指针转换是否破坏严格别名规则?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!