This C code works fine (the compiler is GNU11). I'm sure it can improved since it gives a "dereferencing type-punned pointer" warning, but I don't know exactly how.
A uint8_t array contains 4 bytes that compose a floating point number. These 4 bytes are then stored in a uint32_t variable, and finally casted into a float variable:
uint8_t buffer[];
uint32_t aux = 0;
float value;
/*buffer contains the response from a sensor, containing a floating point number divided in 4 bytes*/
aux = aux | ((buffer[3] << 24) | (buffer[4] << 16));
aux = aux | ((buffer[5] << 8) | (buffer[6]));
value = (float)*((float*)&aux);
Can this code present undefined behavior? I've read that I could use "union" get rid of the warning, but will will this get rid of the undefined behavior too?
Thank you!
The well defined method for type punning is using a memcpy
between variables of the different types. I.e.
memcpy(&value, &aux, sizeof(float));
With optimization enabled and operating variables residing in automatic storage (i.e. regular function variables), this will translate into zero additional instructions, as the compiler will internally perform a single static assignment.
EDIT: Since C99 the other well defined method is using a union
for type punning:
union {
uint8_t u8[sizeof(float)/sizeof(uint8_t)];
uint32_t u32[sizeof(float)/sizeof(uint32_t)];
float flt;
} float_type_punner;