C++ 将4个原始字节转换为32位浮点

C++ 将4个原始字节转换为32位浮点,c++,c,floating-point,floating-point-conversion,C++,C,Floating Point,Floating Point Conversion,我试图从eeprom中重新构造一个32位浮点值 eeprom存储器(0-4)中的4个字节为:B4 A2 91 4D PC(VS Studio)正确地将其重建为3.054199*10^8(我知道的浮点值应该在那里) 现在我把这个eeprom从8位Arduino读取,所以不确定它是否是编译器/平台的东西,但是当我尝试将4个字节读入32位dword,然后将其键入浮点时,我得到的值甚至不接近 假设标准ansi-c编译器无法自动完成转换,那么如何手动将4个字节解析为浮点?您需要在指针级别强制转换 int

我试图从eeprom中重新构造一个32位浮点值

eeprom存储器(0-4)中的4个字节为:B4 A2 91 4D

PC(VS Studio)正确地将其重建为3.054199*10^8(我知道的浮点值应该在那里)

现在我把这个eeprom从8位Arduino读取,所以不确定它是否是编译器/平台的东西,但是当我尝试将4个字节读入32位dword,然后将其键入浮点时,我得到的值甚至不接近


假设标准ansi-c编译器无法自动完成转换,那么如何手动将4个字节解析为浮点?

您需要在指针级别强制转换

int     myFourBytes = /* something */;
float*  myFloat = (float*) &myFourBytes;
cout << *myFloat;

最安全的方法是使用
memcpy
,而且由于编译器优化的速度与其他方法一样快:

uint32_t dword = 0x4D91A2B4;
float f;
memcpy(&f, &dw, 4);
演示:

正如他在回答中所提到的,这可能是一个问题,因为这是您在这种低级操作中可能遇到的唯一逻辑问题。在他链接的问题中,基本上涵盖了处理此类问题的过程,我只想给您留下一些信息:

与安都诺论坛一样,安都诺使用小尾端词。如果您不确定最终要处理的系统的endianness是什么,但希望使代码成为半多平台,则可以在运行时使用简单的代码片段检查endianness:

bool isBigEndian(){
   int number = 1;
   return (*(char*)&number != 1);
}
请注意,正如所有事情一样,这会消耗您的一些进程或时间,并使您的程序运行较慢。虽然这几乎总是一件坏事,但您仍然可以使用它在应用程序的调试版本中查看结果

其工作原理是测试存储在
&number
所指地址的
int
的第一个字节。如果第一个字节不是
1
,则表示字节是大端字节

另外-这仅在
sizeof(int)>sizeof(char)
时有效

您还可以将其嵌入到代码中:

float getFromEeprom(int address){
   char bytes[sizeof(float)];
   if(isBigEndian()){
      for(int i=0;i<sizeof(float);i++)
         bytes[sizeof(float)-i] = EEPROM.read(address+i);
   }
   else{
      for(int i=0;i<sizeof(float);i++)
         bytes[i] = EEPROM.read(address+i);
   }
   float result;
   memcpy(&result, bytes, sizeof(float));
   return result;
}
float getFromEeprom(整数地址){
字符字节[sizeof(float)];
if(isBigEndian()){

对于(int i=0;i像一个没有代码的代码,我们无法确定。在我对这个问题的回答中,我链接到一个转换器,这样你可以尝试翻转值,看看是否可以重复你看到的结果以确认。我同意这可能是endianness。你在Arduino上得到了大约-3.0280572E-7吗?有趣的是,当第一个字节是treat时d作为MSB,编译器(浮点)转换结果:3.03055283E9..但是我确实记得最初看到了-3.02E-7,但不确定为什么我不再看到了。当第一个字节被视为LSB时,编译器强制转换为:1.30138995E9。是如何在PHP中将字节数组转换为浮点。谢谢,我喜欢这一点的美妙之处!它似乎使用了内置的编译器转换,而没有使用separate调用..效果很好!我之所以不使用它,唯一的原因是因为有严格的别名警告..尽管我不确定这是什么意思,但我还是相信比我更有编程经验的人的话,这可能会导致意想不到的问题!这意味着优化器在技术上被允许在这里做可怕的事情,作为一个严格的阅读标准会调用这种未定义的行为。实际上,在主要系统中存在大量现有的生产代码,如果优化器开始清理这些代码,这些代码将被破坏。我认为您可以通过使用int和float的并集来绕过别名问题,而不是在这两种类型之间进行强制转换。谢谢,这很有效太好了!因为我的程序空间几乎满了,所以我将尝试添加一个自定义memcpy实现,这样我就可以避免包含stdlib.h…只是为了不添加其他未使用的code@ben:首先,我会将memcpy原型复制到您的代码中……大多数编译器都能识别名称
memcpy
,并且当大小参数是固定的,而且很小。谢谢,Endity确实起到了作用,但是无论我以何种方式对字节排序,float casting本身都没有给出正确的值。我选择Ben的答案,因为它是第一个答案,但非常喜欢你的代码!
float getFromEeprom(int address){
   char bytes[sizeof(float)];
   if(isBigEndian()){
      for(int i=0;i<sizeof(float);i++)
         bytes[sizeof(float)-i] = EEPROM.read(address+i);
   }
   else{
      for(int i=0;i<sizeof(float);i++)
         bytes[i] = EEPROM.read(address+i);
   }
   float result;
   memcpy(&result, bytes, sizeof(float));
   return result;
}