float的printf()为十六进制数

时间:2017-07-11 14:03:19

标签: c

我很难理解为什么这段代码会导致3f000000

float f = 5e-1;
printf("%x", *(int*)&f);

5 个答案:

答案 0 :(得分:9)

这是未定义的行为:标准不保证指向intfloat的指针具有相同的对齐方式,因此(int*)&f强制转换无效(Q&A)。< / p>

在您的情况下,演员表生成的值与下面的0.5(5e-1)的IEEE-754表示一致:

bin:    0011 1111 0000 0000 0000 0000 0000 0000
        +--- ---- -=== ==== ==== ==== ==== ====
hex:       3    f    0    0    0    0    0    0

其中+是符号位,-是指数位,=是尾数位。

但是,当您在其他系统上运行相同的程序时,或者即使该程序将运行完成,也绝对无法保证同一程序会产生相同的结果。

答案 1 :(得分:5)

您可能更喜欢

void dump(const void *data, size_t len) {
    const unsigned char *x = data;
    printf("%02x", x[0]);
    for (size_t k = 1; k < len, k++) printf(" %02x", x[k]);
    puts("");
}

然后

float f = 5e-1;
dump(&f, sizeof f);

答案 2 :(得分:2)

由于(int*)&f,您的代码行为未定义。由于类型不相关,C风格的演员表无效。

如果要检查与f关联的内存,则C和C ++都允许转换为const unsigned char*,并使用指针算法跟踪内存到sizeof(f)

答案 3 :(得分:2)

由于您不熟悉C / C++ - 我猜 - 您可能对undefined behaviors没有任何想法。简而言之,C / C++语言有些角落不会define应该发生什么。为什么?背后有很多原因,例如性能。在这些情况下,行为的结果或效果完全依赖于实现(编译器 - 更具体地说(例如gcc,vc ++))。

您在此处所做的工作列于What are all the common undefined behaviours that a C++ programmer should know about?

的已接受答案的第7项

答案 4 :(得分:2)

其他人已经解决了未定义的行为,所以我只会解决这个问题:

  

我很难理解为什么这段代码导致3f000000

代码尝试打印浮点值0.5(或5e-1)的二进制表示。

它以非法方式执行此操作 - 请参阅其他答案以了解正确方法 - 请参阅此答案https://stackoverflow.com/a/45036945/4386427

值3f000000的解释是您的系统似乎使用IEEE 754单精度二进制浮点格式(请参阅https://en.wikipedia.org/wiki/Single-precision_floating-point_format)。

格式使用

  • 位31作为符号位(在您的情况下为0)
  • 位30..23为指数(01111110二进制= 7e十六进制=在您的情况下为十六进制126)
  • 位22..0作为分数(在您的情况下全为零)

所以在你的情况下

  • sign is 0
  • 指数为126
  • 分数为0

通常,该值计算如下:

  

value =( - 1)^ sign *(1 + fraction)* 2 ^(exponent - 127)

由于sign和fraction为0,因此很容易计算出值:

  

值= 1 * 1 * 2 ^(126 - 127)= 2 ^ -1 = 0.5

因此,对于IEEE 754单精度二进制浮点,值为0.5的浮点数与二进制模式3f000000一起存储