从指针值分配

时间:2015-06-10 10:30:57

标签: c pointers

我在开源AAC解码器中看到了以下代码,

static void flt_round(float32_t *pf)
{
    int32_t flg;
    uint32_t tmp, tmp1, tmp2;

    tmp = *(uint32_t*)pf;
    flg = tmp & (uint32_t)0x00008000;
    tmp &= (uint32_t)0xffff0000;
    tmp1 = tmp;
    /* round 1/2 lsb toward infinity */
    if (flg)
    {
        tmp &= (uint32_t)0xff800000;       /* extract exponent and sign */
        tmp |= (uint32_t)0x00010000;       /* insert 1 lsb */
        tmp2 = tmp;                             /* add 1 lsb and elided one */
        tmp &= (uint32_t)0xff800000;       /* extract exponent and sign */

        *pf = *(float32_t*)&tmp1 + *(float32_t*)&tmp2 - *(float32_t*)&tmp;
    } else {
        *pf = *(float32_t*)&tmp;
    }
}

在那条线上,

*pf = *(float32_t*)&tmp;

相同
*pf = (float32_t)tmp;

不是吗?

或者有区别吗?也许在表现?

谢谢。

4 个答案:

答案 0 :(得分:1)

不,他们完全不同。假设tmp的值为1.他们的代码将给*pf任何浮点数具有与整数1相同的二进制表示的值。您的代码将给它浮点值1.0!< / p>

答案 1 :(得分:1)

此代码正在编辑浮点值,因为它知道它是使用standard IEEE 754 floating representation格式化的。

*(float32_t*)&tmp;

表示将temp的地址重新解释为32位浮点数上的指针,提取指向的值。

(float32_t)tmp;

表示将整数转换为float 32.这意味着32.1111f可能会产生32

答案 2 :(得分:0)

非常不同。 第一个导致tmp的位模式被重新解释为float。 第二个导致tmp的数值转换为float(在可以表示的精度范围内,包括舍入)。

试试这个:

int main(void) {
    int32_t n=1078530011;

    float32_t f;

    f=*(float32_t*)(&n);
    printf("reinterpet the bit pattern of %d as float - f==%f\n",n,f);

    f=(float32_t)n;
    printf("cast the numerical value of %d as float  - f==%f\n",n,f);

    return 0;
}

示例输出:

reinterpet the bit pattern of 1078530011 as float - f==3.141593
cast the numerical value of 1078530011 as float  - f==1078530048.000000

就像在想那样

const char* str="3568";
int a=*(int*)str;
int b=atoi(str);

将为ab分配相同的值。

答案 3 :(得分:0)

首先回答问题,{​​{1}}根据标准规则(6.3.1.4)安全整数转换为浮点数。

  

当整数类型的值转换为实际浮动类型时,如果   转换的值可以在新类型中准确表示,   它没有变化。如果转换的值在范围内   可以表示但不能准确表示的值,   结果是最接近的较高或最接近的较低的可表示   值,以实现定义的方式选择。如果值正在   转换超出了可以表示的值范围,即   行为未定义。

另一方面,

=SUMIF(A:A,Cat,D:D) 是一个肮脏的技巧,告诉程序整数的二进制内容应该被视为浮点变量,而不用担心。

然而,编写脏技巧的人可能没有意识到它会导致未定义的行为,原因是:它违反了strict aliasing rule

要修复此错误,您必须告诉编译器以非标准,非可移植的方式运行(例如gcc -fno-strict-aliasing),我不建议这样做。

或者最好,您重写代码,以便它不依赖于未定义的行为。最好的方法是以下列方式使用严格别名不适用的联合:

my_float = (float)my_int

最好添加以下健全性检查:

my_float = *(float*)&my_int