我需要保存一个浮点值,它是一个整数值的复制内存。
在reinterpretedFloat
函数中,我创建了一个样本整数并将内存复制到float变量。
当memcpy-ed float返回时,该值值会发生变化。
以下是示例代码。
#include <stdio.h>
#include <stdint.h>
void printHex(const unsigned char* buff, int count)
{
printf("0X");
for (int i = 0; i < count; ++i)
{
printf("\t%X", buff[i]);
}
printf("\n");
}
float reinterpretedFloat()
{
int32_t value = 0x7F845E58;
float tmp;
memcpy(&tmp, &value, sizeof(float));
printHex(reinterpret_cast<const unsigned char*>(&tmp), 4); //memcpy
return tmp;
}
int main()
{
float newFloat = reinterpretedFloat();
printHex(reinterpret_cast<const unsigned char*>(&newFloat), 4); //returned value
return 0;
}
结果就是这样。
0X 58 5E 84 7F(memcpy)
0X 58 5E C4 7F(returned value)
我的期望是0X 58 5E 84 7F
......
任何机构都可以解释为什么会这样? 在x64配置中,这不会发生。
答案 0 :(得分:7)
0x7f845e58是signaling NaN。它被归一化为0x7fc45e58,这是一个安静的NaN,具有相同的有效载荷。
x86-64和32位x86结果之间的区别是因为在前一种模式下,要从float
函数返回reinterpretedFloat()
值,MOVSS
指令来自{{3} ISA扩展将值加载到xmm0
寄存器而不进行任何转换,而在后者上,使用FLD dword [...]
,从32位float
转换为SSE内部80位long double
格式,将信令状态规范化为安静*。
机制上的差异是由于x86-64体系结构保证支持SSE,因此ABI使用它,而i386 ABI不需要它,因为并非所有x86 CPU都支持它。
*从技术上讲,转换会导致无效操作异常,但由于它被屏蔽(默认情况下),因此您可以获得从NaN中删除信令状态的标准化结果