This question is a follow-up to: Is adding to a "char *" pointer UB, when it doesn't actually point to a char array?
In CWG 1314, CWG affirmed that it is legal to perform pointer arithmetic within a standard-layout object using an unsigned char
pointer. This would appear to imply that some code similar to that in the linked question should work as intended:
struct Foo {
float x, y, z;
};
Foo f;
unsigned char *p = reinterpret_cast<unsigned char*>(&f) + offsetof(Foo, z); // (*)
*reinterpret_cast<float*>(p) = 42.0f;
(I have replaced char
with unsigned char
for greater clarity.)
However, it seems that the new changes in C++17 imply that this code is now UB unless std::launder
is used after both reinterpret_cast
s. The result of a reinterpret_cast
between two pointer types is equivalent to two static_cast
s: the first to cv void*
, the second to the destination pointer type. But [expr.static.cast]/13 implies that this produces a pointer to the original object, not to an object of the destination type, since an object of type Foo
is not pointer-interconvertible with an unsigned char
object at its first byte, nor is an unsigned char
object at the first byte of f.z
pointer-interconvertible with f.z
itself.
I find it hard to believe that the committee intended a change that would break this very common idiom, making all pre-C++17 usages of offsetof
undefined.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…