我是什么= *(长*)和y;做? [重复]

问题描述 投票:0回答:3

这个问题在这里已有答案:

我看到以下代码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; 

一般来说,我们使用*&指针,但这里都使用变量。那么,它在这做什么?

c
3个回答
5
投票

该线正在采取float,看着持有float的记忆,重新解释那个记忆作为记忆持有long,并得到那个long。基本上,它将浮点数的位模式重新解释为整数的位模式,以便弄乱它的位。

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


2
投票

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

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

  1. y是我们想要转换的浮点变量。很简单。
  2. &是通常的地址运算符,所以&y是指向y的指针。
  3. (long *)是指向long的指针,所以(long *) &y是一个指向long的指针,指向内存中与y相同的位置。那里没有真正的long,只有float,但如果floatlong都是32位(就像代码所假设的那样),这将给你一个指向long的指针,其具有与float相同的位模式。
  4. 最后,*取消引用指针。因此,完整的表达式,* ( long * ) &y;,给你一个longy相同的位模式。

通常,具有与long相同位模式的float将是无用的,因为它们以完全不同的方式存储数字。然而,对long进行位操作更容易,程序稍后将其转换回`float。


0
投票

它表示y(使其成为指针)的地址转换为long指针,解除引用并分配给i

© www.soinside.com 2019 - 2024. All rights reserved.