Here is has been established that it is illegal to treat tightly packed consecutive struct members of type T as an array of T.
But what about copying the underlying representation?
Given:
struct vec {
float x, y, z;
};
with the the same constraints:
static_assert(sizeof(vec) == 3 * sizeof(float));
is the following:
int main() {
vec v = {1.9f, 2.5f, 3.1f};
float a[3];
std::memcpy(&a, &v, 3 * sizeof(float));
assert(a[0] == v.x);
assert(a[1] == v.y);
assert(a[2] == v.z);
vec u;
std::memcpy(&u, &a, 3 * sizeof(float));
assert(u.x == a[0]);
assert(u.y == a[1]);
assert(u.z == a[2]);
}
legal?
As long as your structure type doesn't have any padding, there's no explicit support for it in the standard, but support for something very close to it can be inferred.
Given a trivially copyable type
T
, what's explicitly allowed is to copy its representation into an array ofchar
(orunsigned char
) and back.There is no requirement that the contents of the array are preserved in the array itself. The contents could be stored in a file, and re-read on a subsequent execution of the program. Or stored in an object of a different type, so long as that type allows it. For this to work, implementations must allow
memcpy
ing representations into objects when those representations did not originate from objects of typeT
in that same run.As a result, at the very least,
should either fail on the first
assert
, or pass. For any representation where it'd fail, it's trivial to create a function which happens to come up with that exact representation in unambiguously valid ways, therefore it mustn't fail.Now, omitting
tmp
here is a bit iffy.std::memcpy
is just repeated assignments of the individual bytes and could have been spelled out explicitly. The semantics of the=
operator imply that for trivially copyable types,a = b;
and{ auto tmp = b; a = tmp; }
are equivalent. Same witha = b; c = d;
and{ auto tmp1 = b; auto tmp2 = d; a = tmp1; c = tmp2; }
, and so on. The former is what a directmemcpy
does, the latter is what twomemcpy
s throughtmp
do.On the other hand, the permission to copy in and out of an array of
char
could be read as requiring an actual array ofchar
, not merely the functional equivalent of it.Personally, I probably would not worry about that unless I actually came across an implementation which uses that interpretation, but if you want to play it safe, you can introduce such a temporary array, and verify that your compiler manages to optimise it away.