Okay, then.
To start with some comments from the original post:
If you think you know what code a given C construct will generate, you've been out of the loop too long.
Modern C compilers can be very aggressive when it comes to optimisation, taking full advantage of the concept of "undefined behaviour", including what used to be obscure cases such as aliasing.
If you need the kind of control you get from assembler, you either need to use assembler, or at least look at the actual assembler code the compiler is generating. If you think you know, think again.
This is an advantage, not a disadvantage.
If you're targeting a specific CPU, you don't need to worry about one of the reasons why casts are problematic: the fact that the standard doesn't actually define representation. You can ignore the fact that ...
Integers may be big-endian, little-endian, Vax-endian or something else; signed integers may use twos-complement, ones-complement, or sign-bit representation; floats could be just about anything; structures may have padding anywhere other than before the first element; pointers may be simple indices into a flat address space or complex structures involving tags, segments and/or whatever else.
You do, however, still need to consider the effects of the cast with respect to C's aliasing rules. The compiler is entitled to assume (with some caveats) that objects with different types do not overlap; modifying one will not affect the other. But casts tend to result in exactly that.
And the "entitled to assume" isn't just for language lawyers any more; modern compilers (at least the ones for desktop/server architectures, which are enveloping an increasing proportion of the "embedded" space) do actually take advantage of that freedom.