0

I am trying to write a program that converts a given decimal value to IEEE representation of 32-bit Hex value. For example: Input: 1.0, Output: 0x3f800000

I store the value in a variable like the following:

    float a = 1.0;

The compiler actually does the conversion of 1.0 to a Hex value. Is it possible to get the Hex value somehow from inside the C program?

Simson
  • 3,373
  • 2
  • 24
  • 38
Amardeep reddy
  • 127
  • 2
  • 10
  • 1
    Tip: Cast it to `char*` and interpret each byte (`sizeof(float)` bytes) as an 8-bit value. – tadman Jan 09 '20 at 01:45
  • 1
    The compiler doesn't convert to a hex value, it shows the internal binary representation as hex just for humans. – tadman Jan 09 '20 at 01:46
  • 2
    As @tadman suggests, declare, `char *p = (char *)&a;` then look at `*p`, `*(p+1)`, etc, for `sizeof(float)` number of bytes. You can print these as hex bytes using `printf`. – lurker Jan 09 '20 at 01:48

4 Answers4

4
float a = 1.0;
uint8_t *hexbytes = (uint8_t *)&a;
printf("0x%02X%02X%02X%02X\r\n", hexbytes[0], hexbytes[1], hexbytes[2], hexbytes[3]);
P.S.
  • 57
  • 3
  • When I execute the code mentioned in the comments or the above answer, I see the following output: 00 00 ffffff80 3f However the expected output is 00 00 80 3f – Amardeep reddy Jan 09 '20 at 02:07
  • 2
    (a) Use `unsigned char` for this, not `char`. `char` may be signed, which will cause the hex displays to have excess Fs where the `char` values are negative. (And, technically, the behavior would not be defined by the C standard.) (b) There is no need for `\r`. (c) This does not account for endianness. – Eric Postpischil Jan 09 '20 at 02:09
  • Remember that results are not portable due to endianness issues. – P.S. Jan 09 '20 at 02:44
3

As long as float and unsigned int are the same width, you can use the following. It is also possible to display the values byte-by-byte, as others have suggested, but then you need to account for endianness.

#include <stdio.h>
#include <string.h>

int main(void)
{
    float a = 1.0f;

    //  Define an object we can easily display in hexadecimal.
    unsigned int x;

    //  Ensure our target object is the same size os float.
    _Static_assert(sizeof a == sizeof x, "Need to use another type, unsigned int is not the same width as float.");

    //  Copy the bytes representing the float into our target object.
    memcpy(&x, &a, sizeof x);

    //  Print the target object in hexadecimal.
    printf("0x%x.\n", x);
}
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • 1
    @tadman: Aliasing through a pointer is not defined by the C standard. Copying bytes, as with `memcpy`, is. Good compilers generally optimize such `memcpy` operations, so it is effectively no operation in the assembly code. – Eric Postpischil Jan 09 '20 at 03:10
  • Ah, as a best-practice then, makes sense. – tadman Jan 09 '20 at 03:33
0

There are a few solutions using pointer answers already here, but you could also achieve this by defining a union where both members are interpreting the same data as different types.

#include <stdint.h>
#include <stdio.h>

int main(){
   union {
            float f;
            uint32_t u;
         } x;
   x.f=1.0;

   printf("%f %e %x\n",x.f, x.f,x.u);

}

Technically this is undefined behaviour in the language standard but implemented as language extension in popular compilers. See longer answers about it here Unions and type-punning

Simson
  • 3,373
  • 2
  • 24
  • 38
-1

Just check if you are missing #include <stdint.h>

#include <stdint.h> // this import is important
float a = 1.0; 
uint32_t u;
void *p;
p = &a;
u = *(uint32_t*)p;
printf("%08X\r\n", u); 
sud007
  • 5,824
  • 4
  • 56
  • 63
P.S.
  • 57
  • 3
  • This causes undefined behaviour (strict aliasing rule) – M.M Jan 09 '20 at 02:25
  • @M.M is rigth, the strict aliasing rule can be avoided using a void* pointer – P.S. Jan 09 '20 at 02:30
  • 1
    using an intermediate `void *` makes no difference ; the strict aliasing rule is about the object being aliased, and the type of the expression accessing it – M.M Jan 09 '20 at 02:31