Title: Building a 32-bit float out of its 4 composite bytes
Tags: c++;floating-point;endianness;portability;single-precision
Question: I'm trying to build a 32-bit float out of its 4 composite bytes. Is there a better (or more portable) way to do this than with the following method?

```#include <iostream&gt;

typedef unsigned char uchar;

float bytesToFloat(uchar b0, uchar b1, uchar b2, uchar b3)
{
    float output;

    *((uchar*)(&amp;output) + 3) = b0;
    *((uchar*)(&amp;output) + 2) = b1;
    *((uchar*)(&amp;output) + 1) = b2;
    *((uchar*)(&amp;output) + 0) = b3;

    return output;
}

int main()
{
    st181a:6c1c:918f:f3a4:2e8c:61d6:1a08:6b16cout << bytesToFloat(0x3e, 0xaa, 0xaa, 0xab) << st181a:6c1c:918f:f3a4:2e8c:61d6:1a08:6b16endl; // 1.0 / 3.0
    st181a:6c1c:918f:f3a4:2e8c:61d6:1a08:6b16cout << bytesToFloat(0x7f, 0x7f, 0xff, 0xff) << st181a:6c1c:918f:f3a4:2e8c:61d6:1a08:6b16endl; // 3.4028234 × 10^38  (max single precision)

    return 0;
}
```

Comment: Considering that this was my first question on Stack Overflow, I'm thrilled at the various responses. I thank everyone for their input.

Here is the accepted answer: You could use  a ```memcpy``` (Result)

```float f;
uchar b[] = {b3, b2, b1, b0};
memcpy(&amp;f, &amp;b, sizeof(f));
return f;
```

or a union* (Result)

```union {
  float f;
  uchar b[4];
} u;
u.b[3] = b0;
u.b[2] = b1;
u.b[1] = b2;
u.b[0] = b3;
return u.f;
```

But this is no more portable than your code, since there is no guarantee that the platform is little-endian or the ```float``` is using IEEE binary32 or even ```sizeof(float) == 4```. 

(Note*: As explained by @James, it is technically not allowed in the standard (C++ §[class.union]/1) to access the union member ```u.f```.)

Comment for this answer: To solve the `sizeof(float)` problem you may just declare the `b` member as `uchar b[sizeof(float)];`.
Comment for this answer: @Matteo: Right, but then the input needs to be modified as well.

Here is another answer: You can use ```st181a:6c1c:918f:f3a4:2e8c:61d6:1a08:6b16copy```:

```float bytesToFloat(uchar b0, uchar b1, uchar b2, uchar b3) 
{ 
    uchar byte_array[] = { b3, b2, b1, b0 };
    float result;
    st181a:6c1c:918f:f3a4:2e8c:61d6:1a08:6b16copy(reinterpret_cast<const char*&gt;(&amp;byte_array[0]),
              reinterpret_cast<const char*&gt;(&amp;byte_array[4]),
              reinterpret_cast<char*&gt;(&amp;result));
    return result;
} 
```

This avoids the union hack, which isn't technically allowed by the language.  It also avoids the commonly used ```reinterpret_cast<float*&gt;(byte_array)```, which violates the strict aliasing rules (it is permitted to reinterpret any object as an array of ```char```, so the ```reinterpret_cast```s in this solution do not violate the strict aliasing rules).

It still relies on ```float``` being four bytes in width and relies on your four bytes being a valid floating point number in your implementation's floating point format, but you either have to make those assumptions or you have to write special handling code to do the conversion.

Comment for this answer: @JoshD:  No; it still relies on `sizeof(float) == 4` and doesn't take endianness into consideration.  It just avoids `reinterpret_cast(some_uchar_array)` and the union hack.
Comment for this answer: @MSalters:  But `memcpy` doesn't reinterpret a byte array as a float; it reinterprets a float as a byte array.
Comment for this answer: I'm fairly certain that `reinterpret_cast(byte_array)` must be allowed if the byte_array (1) is  aligned properly and (2) actually contains a float. I think so because otherwise it would be impossible to `memcpy` a `float` to another `float` (since `memcpy` writes to a byte array), and yet a `float` is the archetypical POD type.
Comment for this answer: It's indeed not `memcpy` itself; that obviously works only on byte arrays. It's the guarantee that you can use the output byte array as a float.

Here is another answer: I typically use this in C -- no ```memcpy``` or ```union``` required. It may break aliasing rules in C++, I don't know.
```float bytesToFloat(uint8_t *bytes, bool big_endian) {
    float f;
    uint8_t *f_ptr = (uint8_t *) &amp;f;
    if (big_endian) {
        f_ptr[3] = bytes[0];
        f_ptr[2] = bytes[1];
        f_ptr[1] = bytes[2];
        f_ptr[0] = bytes[3];
    } else {
        f_ptr[3] = bytes[3];
        f_ptr[2] = bytes[2];
        f_ptr[1] = bytes[1];
        f_ptr[0] = bytes[0];
    }
    return f;
}
```
If you have a whole array of bytes that need to be re-interpreted as floats, you can call the following procedure for each consecutive sequence of 4 bytes in the array if necessary, to switch the byte order (e.g. if you are running on a little endian machine, but the bytes are in big endian order). Then you can simply cast the ```uint8_t *``` array pointer to ```float *```, and access the memory as an array of floats.
```void switchEndianness(uint8_t *bytes) {
    uint8_t b0 = bytes[0];
    uint8_t b1 = bytes[1];
    uint8_t b2 = bytes[2];
    uint8_t b3 = bytes[3];
    bytes[0] = b3;
    bytes[1] = b2;
    bytes[2] = b1;
    bytes[3] = b0;
}
```


Here is another answer: If you want a portable way to do this, you'll have to write a bit of code to detect the endianess of the system.

```float bytesToFloatA(uchar b0, uchar b1, uchar b2, uchar b3)
{
    float output;

    *((uchar*)(&amp;output) + 3) = b0;
    *((uchar*)(&amp;output) + 2) = b1;
    *((uchar*)(&amp;output) + 1) = b2;
    *((uchar*)(&amp;output) + 0) = b3;

    return output;
}


float bytesToFloatB(uchar b0, uchar b1, uchar b2, uchar b3)
{
    float output;

    *((uchar*)(&amp;output) + 3) = b3;
    *((uchar*)(&amp;output) + 2) = b2;
    *((uchar*)(&amp;output) + 1) = b1;
    *((uchar*)(&amp;output) + 0) = b0;

    return output;
}

float (*correctFunction)(uchar b0, uchar b1, uchar b2, uchar b3) = bytesToFloatA;

if ((*correctFunction)(0x3e, 0xaa, 0xaa, 0xab) != 1.f/3.f) // horrifying, I know
{
  correctFunction = bytesToFloatB;
}
```

Comment for this answer: That won't be equal in any endians because `1./3.`  is a `double`, not a `float`. You should use something like `1.0f/3`.

Here is another answer: There's no way to do this portable, since different platforms can use:


different byte ordering (big endian vs. little endian)
different representations for floating point values (see http://en.wikipedia.org/wiki/IEEE_754-1985 for an example)
different sizes for floating point values


I also wonder where you get these 4 bytes from?

If I assume that you get them from another system, and you can guarantee that both systems use exactly the same method to store floating-point values in memory, you can use the union trick.  Otherwise, your code is almost guaranteed to be non-portable.


Here is another answer: The following functions pack/unpack bytes representing a single precision floating point value to/from a buffer in network byte order. Only the pack method needs to take endianness into account since the unpack method explicitly constructs the 32-bit value from the individual bytes by bit shifting them the appropriate amount and then OR-ing them together. These functions are only valid for C/C++ implementations that store a float in 32-bits. This is true for IEEE 754-1985 floating point implementations.

```// unpack method for retrieving data in network byte,
//   big endian, order (MSB first)
// increments index i by the number of bytes unpacked
// usage:
//   int i = 0;
//   float x = unpackFloat(&amp;buffer[i], &amp;i);
//   float y = unpackFloat(&amp;buffer[i], &amp;i);
//   float z = unpackFloat(&amp;buffer[i], &amp;i);
float unpackFloat(const void *buf, int *i) {
    const unsigned char *b = (const unsigned char *)buf;
    uint32_t temp = 0;
    *i += 4;
    temp = ((b[0] << 24) |
            (b[1] << 16) |
            (b[2] <<  8) |
             b[3]);
    return *((float *) &amp;temp);
}

// pack method for storing data in network,
//   big endian, byte order (MSB first)
// returns number of bytes packed
// usage:
//   float x, y, z;
//   int i = 0;
//   i += packFloat(&amp;buffer[i], x);
//   i += packFloat(&amp;buffer[i], y);
//   i += packFloat(&amp;buffer[i], z);
int packFloat(void *buf, float x) {
    unsigned char *b = (unsigned char *)buf;
    unsigned char *p = (unsigned char *) &amp;x;
#if defined (_M_IX86) || (defined (CPU_FAMILY) &amp;&amp; (CPU_FAMILY == I80X86))
    b[0] = p[3];
    b[1] = p[2];
    b[2] = p[1];
    b[3] = p[0];
#else
    b[0] = p[0];
    b[1] = p[1];
    b[2] = p[2];
    b[3] = p[3];
#endif
    return 4;
}
```

Comment for this answer: I'm pretty sure this is undefined behaviour in C++ due to strict aliasing rules.
Comment for this answer: I think there is a mistake in the code line:  return *((float *) temp);
It should be: return *((float *) &temp);
Comment for this answer: ironically, I was looking for a way to cleanly read a float from a binary file, and I ended up being lazy and doing the pointer hack in unpackFloat() above. I googled to find a better way and end up finding someone who did the exact same thing.

{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 6, 'CommentCount': 1, 'ContentLicense': 'CC BY-SA 4.0', 'CreationDate': '2010:00:10/21/10', 'FavoriteCount': 12.0, 'PostTypeId': 1, 'Tags': '<c++><floating-point><endianness><portability><single-precision>', 'Title': 'Building a 32-bit float out of its 4 composite bytes', 'ViewCount': 65468, 'id': 3991478, 'user_AboutMe': None, 'user_AccountId': 138931.0, 'user_DisplayName': 'Madgeek', 'user_Reputation': 373.0, 'user_Views': 20.0, 'user_id': 344190.0}}