【问题标题】:Get float in HEX format以 HEX 格式获取浮点数
【发布时间】:2020-05-08 17:39:55
【问题描述】:

我有字符串char str [8]。它以 HEX 格式表示一个数字。它是浮动的,带有标志。如何将其写入浮点类型的变量?

例如:

char str[9] = "41700000\0";

我需要从中获取 val:15.0

【问题讨论】:

  • char str[8] = "41700000"; 不是字符串,因为它不是以空值结尾的。
  • 很难理解你在问什么。你是说"41700000" 是十六进制的。要将其转换为 32 位 float
  • @FiddlingBits 是的。我做了相反的事情float d = atof(str); printf("%X \n",*(unsigned int*)&d); ,当我输入 15.0 时,它给了我十六进制的数字。我将此与一些可以让您从 Real2Hex 进行转换的网站进行了比较。
  • *(unsigned int*)&d 是 UB。使用unionmemcpy()
  • 也许printf("%.1f\n", ((union { int i; float f; }) { .i = atoi(str) }).f);?

标签: c floating-point hex


【解决方案1】:

你可以双关数据:

  1. 使用 memcpy
unsigned int u = 0x41700000;
float f;

memcpy(&f, &u, sizeof(f));
printf("%f\n", f);
  1. 使用工会(IMO 合法,很多人持相反意见)
union un
{
    float f;
    unsigned u;
};

void foo(unsigned x)
{
    union un a = {.u = x};
    printf("%f\n", a.f);
}

我假设浮点数和整数具有相同的大小。

当然,您必须将字符串从您的问题转换为无符号值 - 但它相对容易(scanf,atoi ....)

顺便说一句,许多编译器会为两者生成完全相同的代码(没有memcpy 调用)https://godbolt.org/z/VaCcxS

【讨论】:

  • 我可以再问一个问题,如何在没有 for 循环的情况下填充前导零?例如:0x3f80x3f800000
  • 0x3f8 << (4 * numberOfZeoes) 假设 0x3f8 是一个数字而不是字符串。
【解决方案2】:

这是一种快速而肮脏的方法,可以将 15 从十六进制的 4 字节表示还原回来。但是,它有太多的错误,甚至不能开始谈论它,而正确的做法是问自己“为什么我需要从这个开始,以及我怎样才能做得更好”。

float hexStrToFloat(const char* str)
{
    union { unsigned int i; float f; } tmp;
    sscanf_s(str, "%x", &tmp.i);
    return(tmp.f);
}

脚注:假定为 little-endian,32 位或更高的机器。

【讨论】:

  • 我相信 *(float*)&tmp 是 UB 由于别名问题。
  • @ chux - 恢复 Monica,该 int 至少有 4 个字节(假设是 32 位机器或更高版本),C 风格将指针转换为浮点指针并将其取消引用。 . 不要认为有任何可以想象的(技术)问题。但是,嘿,几乎是浮点数的二进制转储,并试图通过直接将该二进制表示解包回变量来将其转换回浮点......这在很多层面上都是错误的。
  • 建议查看What is the strict aliasing rule?。另外:这不是尺寸问题。
  • 我的意思是,你能想象在任何情况下,编译器会以一种尴尬的方式优化它并做一些其他事情,而不是将 tmp 放在堆栈上吗?无论如何,修改答案以不使用此演员表,但做的几乎相同......
  • 我可以想象一种情况。当编译器优化并且您的代码具有 UB 时,今天的编译器不是您的朋友。我怀疑我可以在评论空间中说服。如果不相信,您可能需要研究或发布问题。
猜你喜欢
  • 2011-08-05
  • 2015-02-08
  • 1970-01-01
  • 2010-12-16
  • 2015-12-12
  • 1970-01-01
  • 2017-12-08
  • 2013-11-12
  • 1970-01-01
相关资源
最近更新 更多