1

我有这段代码输出错误的结果。

#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;
}

我得到的输出是

字节 0xc0000000 浮点数 -2.000001e+00

我期待得到

字节 0xdeadbeef 浮点数 -6.2598534e+18

编辑#1,正如指出的那样,字节顺序可能不同,这将导致以下结果

字节 0xefbeadde 浮点数 -1.1802469e+29

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

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

4

5 回答 5

8

这不是 memcpy 的问题。

  1. float总是double在传递...printf 时转换为,因此在大多数英特尔架构上您无法获得 4 个字节。
  2. 当您0xdeadbeef在此代码中进行扩展时,您假设您的架构是 BIG endian。有许多小端架构,例如 Intel x86。
于 2009-05-09T08:33:57.557 回答
6

您确实意识到当传递给像 printf() 这样的可变参数函数时,浮点数会被提升为双倍?所以当你说:

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

您正在尝试将真正的两个 8 字节值视为两个 4 字节值,从而给出(我相信)未定义的行为。

于 2009-05-09T08:22:07.600 回答
2

printf 中的“%x”需要一个无符号整数。你给它一个浮点数,它会自动转换,这不是你想要的。你想做这样的事情:

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

哦,正如其他人指出的那样,如果您使用的是 x86,您将不会看到 0xdeadbeef,更像是 0xefbeadde。

于 2009-05-09T08:40:41.377 回答
1

看看这是否更好:

printf("bytes 0x%x float %e\n", *(int *)&flt, flt);
于 2009-05-09T08:40:43.000 回答
1

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

bytes 0xefbeadde float -1.860545e+230

0xefbeadde 是 deadbeaf 的大端序。double 的最后 4 个字节未定义,因此 float 后显示的数字会有所不同。

您提到它可以在另一台计算机上运行,​​那是什么类型的计算机?一定是小端,其中 sizeof(float) == sizeof(double) :)

于 2009-05-09T08:58:18.573 回答