Consider the following snippet as an example:
*pInt = 0xFFFF;
*pFloat = 5.0;
Since they are int
and float
pointers, the compiler will assume they don't alias and can exchange them for example.
Now let's assume we spice it up with this:
*pInt = 0xFFFF;
*pChar = 'X';
*pFloat = 5.0;
Since char*
is allowed to alias anything, it may point to *pInt
, so the assignment to *pInt
cannot be moved beyond the assignment of *pChar
, because it may legitimately point to *pInt
and set its first byte to 'X'.
Similarly pChar
may point to *pFloat
, assignment to *pFloat
cannot be moved before the char assignment, because the code may intend to nullify the effects of the previous byte setting by reassigning the *pFloat
.
Does this mean I can write and read through char*
to create barriers for rearrangement and other strict aliasing related optimizations?
Pointer aliasing mostly makes sense in scenarios when the compiler can't know if a pointer variable alias another pointer or not. As in the case when you compile a function located in a different translation unit than the caller.
void func (char* pChar, float* pFloat)
{
*pChar = 'X';
*pFloat = 5.0;
}
Here the pFloat
assignment can indeed not be sequenced before the pChar
one, because the compiler can't deduct that pChar
does not point at the same location as pFloat
.
However, when facing this scenario, the compiler can (and probably will) add a run-time check to see if the addresses could be pointing at overlapping memory or not. If they do, then the code must be sequenced in the given order. If not, then the code may be re-organized and optimized.
Meaning that you would only get memory barrier-like behavior in case the pointers actually do alias/point at overlapping memory. If not, then all bets regarding instruction ordering would be off. So this is probably not a mechanism that you should rely upon.