这个指针转换是否破坏严格别名规则? [英] Does this pointer casting break strict aliasing rule?

查看:200
本文介绍了这个指针转换是否破坏严格别名规则?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆