I have uint8_t size 4 integers stored in a array: uint8_t sdo_rx_data_buffer[OD_entry_len];
. The length of this array is 4 bytes (OD_entry_len = 4), so is equal to float size (32 bits). I need to convert this array into float variable. For exampe, I have these values:
int array[4] = {0xd0, 0x69, 0x83, 0x3f};
And i should get
float i_motor = 1.02666664;
Any ideas how to convert it?
CodePudding user response:
Assuming that you know that the binary representation gives a valid floating point number on your system and you got the endianess right, then you can use a union
:
#include <stdint.h>
#include <stdio.h>
typedef union
{
uint8_t raw [sizeof(float)];
float f;
} float_converter;
int main (void)
{
float_converter fc = { .raw = {0xd0, 0x69, 0x83, 0x3f} };
printf("%f\n", fc.f);
}
Output on x86_64 Linux:
1.026667
CodePudding user response:
One incorrect way which may seem to work would be to reinterpret the array using a pointer.
uint8_t array[4] = {0xd0, 0x69, 0x83, 0x3f};
float *p = (float*)array;
printf( "%f\n", *p );
However, this code has undefined behavior, because it violates the strict aliasing rule. It may also have alignment issues.
On the compilers gcc and clang, you can use __attribute__((__may_alias__))
on the pointer p
, so that there is no strict aliasing violation:
uint8_t array[4] = {0xd0, 0x69, 0x83, 0x3f};
float __attribute__((__may_alias__)) *p = (float*)array;
printf( "%f\n", *p );
However, there still may be alignment issues.
A different way, which fully complies with the ISO C standard (and therefore should work on all compilers), would be to use memcpy
instead:
uint8_t array[4] = {0xd0, 0x69, 0x83, 0x3f};
float f;
memcpy( &f, array, sizeof f );
printf( "%f\n", f );
Most compilers will optimize away the memcpy
when compiler optimizations are active.
Beware of endianness issues, though. The posted code will only work on little-endian platforms.