繁体   English   中英

浮点数的Printf()作为十六进制数

[英]Printf() of a float as hexadecimal number

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

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

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

在您的情况下,强制转换产生的值与以下的IEEE-754表示形式0.5(5e-1)一致:

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

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

但是,绝对不能保证在其他系统上运行该程序时,该程序将产生相同的结果,甚至无法保证该程序将运行至完整状态。

您可能更喜欢

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);

由于(int*)&f ,代码的行为未定义。 C类型转换无效,因为类型无关。

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

因为您是C / C++新手,所以-您可能对undefined behaviors没有任何想法。 简而言之,在某些方面, C / C++语言没有define应该确切发生的事情。 为什么? 背后有很多原因,例如性能。 在那些情况下,行为的结果或效果完全取决于实现(编译器-更具体地说(例如gcc,vc ++))。

C ++程序员应该知道的所有常见未定义行为是在已接受答案的第7条中列出的

其他人已经解决了未定义的行为,所以我只解决这一部分:

我很难理解为什么此代码会导致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作为分数(在您的情况下全为零)

所以你的情况

  • 符号是0
  • 指数是126
  • 分数是0

通常,该值计算为:

值=(-1)^符号*(1 +分数)* 2 ^(指数-127)

由于符号和小数均为0,因此很容易计算出该值:

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM