C++ memcpy没有做它应该做的事

C++ memcpy没有做它应该做的事,c++,c,memcpy,C++,C,Memcpy,我有一段代码输出了错误的结果 #include <stdio.h> #include <string.h> int main() { unsigned char bytes[4]; float flt=0; bytes[0]=0xde; bytes[1]=0xad; bytes[2]=0xbe; bytes[3]=0xef; memcpy( &flt, bytes, 4); printf("bytes 0x%x float

我有一段代码输出了错误的结果

#include <stdio.h>
#include <string.h>

int main() 
{
  unsigned char bytes[4];
  float flt=0;

  bytes[0]=0xde;
  bytes[1]=0xad;
  bytes[2]=0xbe;
  bytes[3]=0xef;

  memcpy( &flt, bytes, 4);

  printf("bytes 0x%x float %e\n", flt, flt);
  return 0;
}
#包括
#包括
int main()
{
无符号字符字节[4];
浮点数flt=0;
字节[0]=0xde;
字节[1]=0xad;
字节[2]=0xbe;
字节[3]=0xef;
memcpy(&flt,字节,4);
printf(“字节0x%x浮点%e\n”,flt,flt);
返回0;
}
我得到的输出是

字节0xc0000000浮点-2.000001e+00

我期待着得到一份工作

字节0xdeadbeeffloat-6.2598534e+18

编辑#1 正如所指出的,endianness可能不同,这将导致以下情况

字节0xefbeadde浮点-1.1802469e+29

我不明白的是,从float到unsigned int的转换导致0xc000000(同一printf语句中的float为-2.0000,我将其归因于编译器优化)


这是以前在另一台计算机上工作过的。这可能是架构上的改变。

您确实意识到,当传递给变量参数函数(如printf())时,浮点值会提升为双精度?所以当你说:

printf("bytes 0x%x float %e\n", flt, flt);
您试图将真正的两个8字节值视为两个4字节值
值,给出(我相信)未定义的行为。

您确实意识到,当传递给变量参数函数(如printf())时,浮点值将被提升为双精度?所以当你说:

printf("bytes 0x%x float %e\n", flt, flt);
您试图将真正的两个8字节值视为两个4字节值
价值观,给予(我相信)未定义的行为。

这不是记忆的问题

  • float
    在通过printf的
    ..
    时始终转换为
    double
    ,因此在大多数英特尔体系结构上无法获得4字节
  • 当您在此代码中表达
    0xdeadbeef
    时,您假定您的体系结构是BIG-endian。有许多小端体系结构,例如Intel x86

  • 这不是记忆的问题

  • float
    在通过printf的
    ..
    时始终转换为
    double
    ,因此在大多数英特尔体系结构上无法获得4字节
  • 当您在此代码中表达
    0xdeadbeef
    时,您假定您的体系结构是BIG-endian。有许多小端体系结构,例如Intel x86
  • printf中的“%x”需要一个无符号int。您给它的是一个自动转换的浮点,而这不是您想要的。您希望执行以下操作:

    printf("bytes 0x%x float %e\n", *((unsigned int *)&flt), flt);
    
    哦,正如其他人所指出的,如果你在x86上,你不会看到0xdeadbeef,更像0xefbeadde。

    printf中的“%x”需要一个未签名的int。你给它一个自动转换的浮点,这不是你想要的。您希望执行以下操作:

    printf("bytes 0x%x float %e\n", *((unsigned int *)&flt), flt);
    

    哦,正如其他人所指出的,如果您在x86上,您不会看到0xdeadbeef,更像0xefbeade。

    看看这是否更好:

    printf("bytes 0x%x float %e\n", *(int *)&flt, flt);
    

    看看这是否更好:

    printf("bytes 0x%x float %e\n", *(int *)&flt, flt);
    

    要查看参数升级,请将声明从float更改为double。在我的机器上,它打印:

    bytes 0xefbeadde float -1.860545e+230
    
    0xefbeadde是死区的大端。double的最后4个字节未定义,因此float之后显示的数字将有所不同


    你提到它在另一台计算机上工作,那是什么类型的计算机?必须是小尾数,其中sizeof(float)==sizeof(double):

    若要查看参数提升,请将声明从float更改为double。在我的机器上,它打印:

    bytes 0xefbeadde float -1.860545e+230
    
    0xefbeadde是死区的大端。double的最后4个字节未定义,因此float之后显示的数字将有所不同


    你提到它在另一台计算机上工作,那是什么类型的计算机?一定是small endian,其中sizeof(float)==sizeof(double):

    没有意识到这是十六进制部分的printf问题。我不明白为什么浮点不能正确地转换成双精度浮点。将浮点转换成双精度浮点不仅仅是将四个字节向右移动:转换确保浮点中的3.14表示双精度浮点中的3.14。升级到double后,printf()将被传递四个字节,其中%x告诉它需要两个字节。因此%x之后的所有内容都是偏离基准的。我没有意识到这是十六进制部分的printf问题。我不明白为什么浮点不能正确地转换成双精度浮点。将浮点转换成双精度浮点不仅仅是将四个字节向右移动:转换确保浮点中的3.14表示双精度浮点中的3.14。升级到double后,printf()将被传递四个字节,其中%x告诉它需要两个字节。因此,在%x之后的所有内容都偏离了基准。