我在开源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;
不是吗?
或者有区别吗?也许在表现?
谢谢。
答案 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);
将为a
和b
分配相同的值。
答案 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