On the heels of a specific problem, a self-answer and comments to it, I'd like to understand if it is a proper solution, workaround/hack or just plain wrong.
Specifically, I rewrote code:
T x = ...;
if (*reinterpret_cast <int*> (&x) == 0)
...
As:
T x = ...;
if (*reinterpret_cast <volatile int*> (&x) == 0)
...
with a volatile
qualifier to the pointer.
Let's just assume that treating T
as int
in my situation makes sense. Does this accessing through a volatile
reference solve pointer aliasing problem?
For a reference, from specification:
[ Note: volatile is a hint to the implementation to avoid aggressive optimization involving the object because the value of the object might be changed by means undetectable by an implementation. See 1.9 for detailed semantics. In general, the semantics of volatile are intended to be the same in C++ as they are in C. — end note ]
EDIT:
The above code did solve my problem at least on GCC 4.5.
Well, anything regarding
volatile
is somewhat unclear in the standard. I mostly agreed with your answer, but now I would like to slightly disagree.In order to understand what
volatile
means, the standard is not clear for most people, notably some compiler writers. It is better to think: when usingvolatile
(and only when), C/C++ is pretty much high level assembly.When writing to a
volatile
lvalue, the compiler will issue a STORE, or multiple STORE if one is not enough (volatile
does not imply atomic).When writing to a
volatile
lvalue, the compiler will issue a LOAD, or multiple LOAD if one is not enough.Of course, where there is no explicit LOAD or STORE, the compiler will just issue instructions which imply a LOAD or STORE.
sellibitze gave the best solution: use
memcpy
for bit reinterpretations.But if all accesses to a memory region are done with
volatile
lvalues, it is perfectly clear that the strict aliasing rules do not apply. This is the answer to your question.Volatile can't help you avoid undefined behaviour here. So, if it works for you with GCC it's luck.
Let's assume T is a POD. Then, the proper way to do this is
There! No strict aliasing problem and no memory alignment problem. GCC even handles memcpy as an intrinsic function (no function call is inserted in this case).