具有相同参数的函数不返回相同的值

问题描述

我通过尝试优化某些东西(更少的变量等)来“玩”fast inverse sqrt 函数。最终代码如下:

float Q_rsqrt(float x) {
    const float x2 = x * 0.5F;
    uint_fast32_t i;
    memcpy(&i,&x,sizeof(float));
    i = 0x5f3759df - ( i >> 1 );
    memcpy(&x,&i,sizeof(float));
    return x * ( 1.5F - ( x2 * x * x ) );
}

首先,了解在我的架构中 uint_fast32_t 以 64 位表示而 float 以 32 位表示是很有用的。因此,在不同大小的变量类型上生成 memcpy() 可能会令人惊讶。 我在编译代码后遇到的问题,每次使用相同参数调用函数都会给出相同的返回值:有时这是负数,有时是正值(但始终具有相同的绝对值)。 memcpy() 的用处是绕过以下代码的警告(取消引用类型双关指针将破坏严格别名规则)(完全按预期工作):

float Q_rsqrt_test(float x) {
    const float xHalf = x * 0.5F;
    const uint_fast32_t i = 0x5f3759df - ( (* ( uint_fast32_t * ) &x) >> 1 );
    x = * ( float * ) &i;
    return x * ( 1.5F - ( xHalf * x * x ) );
}

对于这段代码,我想说没有类型大小的问题,因为源代码(在上面的链接上可见)已经使用了 double type,它在我的架构上以 64 位表示(而不是float 的 32 位)。

我真的不明白为什么我可以用第一个函数得到否定的答案...

感谢您的帮助。

解决方法

正如 Barmar 所说,将 i 初始化为 0 有效。我还认为最好避免取消引用具有其他大小的类型(例如 *(uint64_t *) &x,其中 x 是浮点数)。使用 uint32_t 取消引用可能会更好,然后将结果正确转换为 64 位变量。