我是什么= *(长*)& y;做?

时间:2017-12-22 19:56:09

标签: c

我看到了以下代码here

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 the heck? 
    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;
}

我不理解以下行。

i  = * ( long * ) &y; 

通常,我们使用*&指针,但这里都使用变量。那么,它在这里做了什么?

3 个答案:

答案 0 :(得分:5)

这一行是float,查看持有float的内存,将该内存重新解释为持有long的内存,然后获取long。基本上,它将浮点数的位模式重新解释为整数的位模式,以便弄乱它的位。

不幸的是,该代码也错误。由于here所述的原因,您不能取消引用该转换指针。在C中,重新解释位模式的唯一方法是通过memcpy。 (根据C变体和实现,通过联合也可以。)

答案 1 :(得分:2)

首先,免责声明:这是技术上未定义的行为,因为它违反strict aliasing rule,但大多数编译器会执行以下操作,我不知道首次编写时的标准情况。

当你看表达式时,有四个主要部分:(

  1. y是我们要转换的浮点变量。很简单。
  2. &是通常的地址运算符,因此&y是指向y的指针。
  3. (long *)是指向long的指针,因此(long *) &y是一个指针指向内存中与y所在位置相同的位置。那里没有真正的long,只有一个float,但如果floatlong都是32位(就像代码所假设的那样),这会给你一个指向与long具有相同位模式的float
  4. 最后,*取消引用指针。因此,完整表达式* ( long * ) &y;为您提供与long具有相同位模式的y
  5. 通常,与long具有相同位模式的float将毫无用处,因为它们以完全不同的方式存储数字。但是,对long执行位操作会更容易,程序稍后会将其转换回`float。

答案 2 :(得分:0)

这意味着y(使其成为指针)的地址转换为long指针,取消引用并分配给i