-1

I have the string char str [8]. It says a number in the HEX format. It is float and with a sign. How can I write it to a variable of type float?

For example:

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

I need get val from this: 15.0

Sam
  • 17
  • 1
  • 3

2 Answers2

1

This is a quick and dirty way to revert your 15 back from the hexadecimal 4 bytes representation. There is too much wrong with it to even start talking about it, though, and the right thing to do would be to ask yourself "why do i need this to begin from, and how can i do something better instead".

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

Footnote: assumes little-endian, 32 bit or higher, machine.

Boris Lipschitz
  • 1,514
  • 8
  • 12
  • I believe `*(float*)&tmp` is UB due to aliasing issues. – chux - Reinstate Monica May 08 '20 at 18:00
  • @ chux - Reinstate Monica, there are at least 4 bytes where that int is (assuming 32 bit machine or higher), C-style casting a pointer there and de-refing it as float pointer... don't think there is a (technical) problem with that in any way imaginable. But hey, taking whats pretty much is a binary dump of a floating point number and trying to convert it back to floating point by directly unpacking that binary representation back into a variable... thats just wrong on so many levels to begin from. – Boris Lipschitz May 08 '20 at 18:10
  • Suggest reviewing [What is the strict aliasing rule?](https://stackoverflow.com/a/98702/2410359). Aside: it is not a size issue. – chux - Reinstate Monica May 08 '20 at 18:19
  • I mean, can you imagine any situation, in which a compiler would optimize this in an awkward way and do something else other than putting tmp on stack? Anyway, modifying the answer to go without this cast, but do pretty much the same... – Boris Lipschitz May 08 '20 at 18:29
  • I can imagine a situation. Compilers today are _not your friend_ when they optimize and your code has UB. I doubt I can convince in comment space. If unconvinced, you may want to research or post a question. – chux - Reinstate Monica May 08 '20 at 18:33
  • Well, better be safe than sorry, using a union instead pretty much tells the compiles "hey, i WANT to overlay those types on top of each other, don't do anything funny with that", so i've edited the answer to just use union. – Boris Lipschitz May 08 '20 at 18:35
  • I truly hope we all agree its generally better to avoid this entire idea of taking hex dumps and putting them back into variables in general, though. – Boris Lipschitz May 08 '20 at 18:40
  • Agree - except through `unsigned char[]` is OK. Anything else has _issues_. – chux - Reinstate Monica May 08 '20 at 18:43
1

You can pun the data:

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

memcpy(&f, &u, sizeof(f));
printf("%f\n", f);
  1. Using union (IMO legal, many people have opposite opinion)
union un
{
    float f;
    unsigned u;
};

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

I assume floats && integers have the same size.

Of course you will have to convert string from your question to the unsigned value - but it is relatively easy (scanf, atoi ....)

PS BTW many compilers will generate exactly the same code for both (without the memcpy call) https://godbolt.org/z/VaCcxS

0___________
  • 60,014
  • 4
  • 34
  • 74