Blackfin:
I think you can use a union to do this despite it being "against the rules", as long as that's all you use the union for. If you use a union to store a bunch of different types of different sizes to, say, save memory usage then, yes, you're going to get unpredictable results if you switch active members randomly.
If you create a union of a float type and a byte-array of size sizeof( float ) then you should be reasonably safe as long as you get the Endian-ness right.
I don't understand how there can still be a discussion about this.
If you use unions or pointer aliasing for type punning, your code is simply ill-formed. Period. It violates the standard, and you have no guarantee whatsoever that it will still work tomorrow.
I don't see why using a union to store a bunch of different types of different sizes would be bad, and using it for type punning would be perfectly fine.
If you can back up this claim using concrete evidence from the standard, I'll gladly change my views, but please, spreading misinformation doesn't help anyone.
GolamMostafa:
Else, one has to go with the following cryptic codes which are not practically liked by the pupils:
float y;
long ptr;
ptr = (long)&y;
*ptr = 0x4091999A;
Serial.print(y, 2); //shows: 4.55
As mentioned before, this code is not valid either. See reply #12 and #14
The only valid solution I'm aware of, and the one that's encouraged by the C++ Core Guidelines is to use a memcpy, which is, in my eyes, a perfectly sensible solution, you're using the memory contents of one object for another object.
If you're worried about the overhead caused by memcpy, don't be, compiler designers are aware of this use of the function, and will optimize it out in pretty much all cases.
Check out this on the Compiler Explorer: Compiler Explorer
#include <stdint.h>
#include <string.h>
// See ยงC.183 of the C++ Core Guidelines
// https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Ru-pun
// Good: using memcpy
float bytesToFloat(uint8_t (&bytes)[4]) {
static_assert(sizeof(float) == 4, "float size expected to be 4 bytes");
float result;
memcpy(&result, bytes, 4);
return result;
}
// BAD! Don't do this, type punning using a union is not allowed
float bytesToFloatUnion(uint8_t (&bytes)[4]) {
union {
uint32_t u32;
float f;
} u;
u.u32 = ((uint32_t) bytes[0] << 0)
| ((uint32_t) bytes[1] << 8)
| ((uint32_t) bytes[2] << 16)
| ((uint32_t) bytes[3] << 24);
return u.f;
}
// BAD! Don't do this, it breaks the strict aliasing rule
float bytesToFloatAliasing(uint8_t (&bytes)[4]) {
float result;
uint32_t* const py = (uint32_t*) &result;
*py = ((uint32_t) bytes[3] << 24) |
((uint32_t) bytes[2] << 16) |
((uint32_t) bytes[1] << 8) |
((uint32_t) bytes[0] << 0);
return result;
}
As you can see, the three functions compile to the exact same machine code when optimizations are enabled. In this case, the memcpy version obviously wins, because it's the only valid one, it's just as fast as the other two, and it has the least amount of code.
Even when optimizations are turned off using -O0 (why would you do that?), the memcpy version boils down to 35 instructions, the union version to 83 (!) instructions, and the pointer aliasing version to 93 (!) instructions.
Clearly, memcpy wins here as well, it's almost three times faster than the pointer version, and more than two times faster than the union version.
If you tune down optimizations for debugging, using -Og, the memcpy version is optimized entirely, it's just 5 instructions, while the union and pointer versions aren't optimized: 46 and 43 instructions respectively.
In this case, the memcpy version is 9 times faster.
This optimization is possible because you're telling the compiler exactly what you want to do, instead of hiding it behind obscure pointer manipulations or union abuse.
I really hope we can finally settle this, too much bad code has been promoted already.
TL;DR
Using unions or pointer aliasing for type punning is illegal.
Using memcpy is the only valid option, and on top of that it is much faster than the other two, and the code is shorter and more readable.