I've been using std::memcpy
to circumvent strict aliasing for a long time.
For example, inspecting a float
, like this:
float f = ...;
uint32_t i;
static_assert(sizeof(f)==sizeof(i));
std::memcpy(&i, &f, sizeof(i));
// use i to extract f's sign, exponent & significand
However, this time, I've checked the standard, I haven't found anything that validates this. All I found is this:
For any object (other than a potentially-overlapping subobject) of trivially copyable type T, whether or not the object holds a valid value of type T, the underlying bytes ([intro.memory]) making up the object can be copied into an array of char, unsigned char, or std?::?byte ([cstddef.syn]).40 If the content of that array is copied back into the object, the object shall subsequently hold its original value. [?Example:
#define N sizeof(T)
char buf[N];
T obj; // obj initialized to its original value
std::memcpy(buf, &obj, N); // between these two calls to std?::?memcpy, obj might be modified
std::memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar type holds its original value
—?end example?]
and this:
For any trivially copyable type T, if two pointers to T point to distinct T objects obj1 and obj2, where neither obj1 nor obj2 is a potentially-overlapping subobject, if the underlying bytes ([intro.memory]) making up obj1 are copied into obj2,41 obj2 shall subsequently hold the same value as obj1. [?Example:
T* t1p;
T* t2p;
// provided that t2p points to an initialized object ...
std::memcpy(t1p, t2p, sizeof(T));
// at this point, every subobject of trivially copyable type in *t1p contains
// the same value as the corresponding subobject in *t2p
—?end example?]
So, std::memcpy
ing a float
to/from char[]
is allowed, and std::memcpy
ing between the same trivial types is allowed too.
Is my first example (and the linked answer) well defined? Or the correct way to inspect a float
is to std::memcpy
it into a unsigned char[]
buffer, and using shift
s and or
s to build a uint32_t
from it?
Note: looking at std::memcpy
's guarantees may not answer this question. As far as I know, I could replace std::memcpy
with a simple byte-copy loop, and the question will be the same.
See Question&Answers more detail:
os