When you first learn about 'cool hacks' like these, you'll want to use everywhere.
Then you'll realize that they don't apply to certain data types in certain environments.
Then you'll come to realize that the rules governing which hacks to use are too complex to remember.
Then you'll want to write a program that figures it out for you.
Then you'll realize that those programs already exist, and they are called compilers.
So now you are back where you started. You have made no progress, but you have gained an important insight.
There's a reason a lot of these potentially non-portable tricks show up in high-performance computing (particularly in videogames) and in the embedded space.
Otherwise, remember the first rule of code optimization for beginners: "Don't."
EDIT: And by "they don't apply", I mean they can crash your program or even silently corrupt your data.
For games, this can mean a higher frame rate. For data processing, it can mean the data gets processed significantly faster. It's especially important for things like video encoders, where even a 1% savings in CPU time can translate directly to 1% more potential revenue for the same operating cost at a company that relies heavily on video encoding.
Yeah, saving those cycles doesn't really mean anything to a beginner, but they can be a huge savings for high performance computation applications.
union { int i; float f;} u; u.i=*i;
Now u.f contains the same bit pattern as the integer pointed to by "i" but interpreted as a float.
Compilers know how to generate code efficiently out of this.
Iirc this is implementation defined behavior, e.g. things like endianness alignment or padding, but it's not undefined behavior, whose evil effects can bubble up in unexpected parts of the program that apparently don't even touch the bad cast.
float f;
memcpy(&f, i, sizeof f);
Don't worry about the implied overhead of the call to memcpy; the compiler will replace it with an intrinsic and emit the expected movss instruction.Back in my C++ days, I would much prefer pointer-cast to union-struct, because the latter was subject to alignment/padding issues you mention, while for the former, I know of no desktop architecture that could mess up a int* -> float* cast.
I'm also doubly surprised because being able to do that stuff is what I'd consider the selling point of C/C++ over higher-level languages.
Yeah, C and C++ aren't the language most people think they are, and the strict aliasing rules are the most clear manifestation of that.
The replacement is often "gcc with inline assembly" or "gcc with lots of __attribute__ extensions such as __may_alias__" or "gcc with optimizations disabled".
The need doesn't go away, despite the wishes of a language committee now dominated by compiler suppliers. From day 1, long before the language was standardized and even before the original (not ANSI) book was published, C was being used with aliasing. It was, after all, developed to support the creation of Unics (before that became UNIX).
> Accessing an object by means of any other lvalue expression (other than unsigned char) is undefined behavior
https://wiki.sei.cmu.edu/confluence/display/c/EXP39-C.+Do+no...
That said, memcpy and a compiler that understand the memcpy intrinsic is probably safer; that said I have a vague memory of hitting an embedded compiler where memcpy wasn't an intrinsic