Convert int bits to float verbatim and print them

Viewed 110

I'm trying to just copy the contents of a 32-bit unsigned int to be used as float. Not casting it, just re-interpreting the integer bits to be used as float. I'm aware memcpy is the most-suggested option for this. However, when I do memcpy from uint_32 to float, and print out the individual bits, I see they are quite different.

Here is my code snippet:

#include <iostream>
#include <stdint.h>
#include <cstring>

using namespace std;

void print_bits(unsigned n) {
  unsigned i;
  for(i=1u<<31;i > 0; i/=2)
    (n & i) ? printf("1"): printf("0");
}

union {
    uint32_t u_int;
    float u_float;
} my_union;

int main()
{
    uint32_t my_int =  0xc6f05705;
    float my_float;
    //Method 1 using memcpy
    memcpy(&my_float, &my_int, sizeof(my_float));
    //Print using function
    print_bits(my_int);
    printf("\n");
    print_bits(my_float);
    //Print using printf
    printf("\n%0x\n",my_int);
    printf("%0x\n",my_float);
    //Method 2 using unions
    my_union.u_int = 0xc6f05705;
    printf("union int = %0x\n",my_union.u_int);
    printf("union float = %0x\n",my_union.u_float);
    return 0;
}

Outputs:

11000110111100000101011100000101
11111111111111111000011111010101
c6f05705
400865
union int = c6f05705
union float = 40087b

Can someone explain what's happening? I expected the bits to match. Didn't work with a union either.

1 Answers

You need to change the function print_bits to

inline
int is_big_endian(void)
{
    const union
    {
        uint32_t i;
        char c[sizeof(uint32_t)];
    } e = { 0x01000000 };

    return e.c[0];
}

void print_bits( const void *src, unsigned int size )
{
    //Check for the order of bytes in memory of the compiler:
    int t, c;
    if (is_big_endian())
    {
        t = 0;
        c = 1;
    }
    else
    {
        t = size - 1;
        c = -1;
    }
    for (; t >= 0 && t <= size - 1; t += c)
    {   //print the bits of each byte from the MSB to the LSB
        unsigned char i;
        unsigned char n = ((unsigned char*)src)[t];
        for(i = 1 << (CHAR_BIT - 1); i > 0; i /= 2)
        {
            printf("%d", (n & i) != 0);
        }
    }
    printf("\n");
}

and call it like this:

int a = 7;
print_bits(&a, sizeof(a));

that way there won't be any type conversion when you call print_bits and it would work for any struct size.

EDIT: I replaced 7 with CHAR_BIT - 1 because the size of byte can be different than 8 bits.

EDIT 2: I added support for both little endian and big endian compilers.

Also as @M.M suggested in the comments if you want to you can use template to make the function call be: print_bits(a) instead of print_bits(&a, sizeof(a))

Related